Filtering...

acl2-doc

books/system/doc/acl2-doc

Included Books

top
other
(in-package "ACL2")
include-book
(include-book "xdoc/top" :dir :system)
*acl2-url*constant
(defconst *acl2-url*
  "https://www.cs.utexas.edu/users/moore/acl2/v8-6/")
acl2-url-reffunction
(defun acl2-url-ref
  (path s)
  (concatenate 'string
    "<a href='"
    (concatenate 'string *acl2-url* path)
    "'>"
    s
    "</a>"))
combined-manual-reffunction
(defun combined-manual-ref
  nil
  (concatenate 'string
    "<a href='"
    (concatenate 'string
      *acl2-url*
      "combined-manual/index.html")
    "'>"
    "ACL2+Books Manual"
    "</a>"))
clhsfunction
(defun clhs
  (url title)
  (declare (xargs :guard (and (or (not url) (stringp url)) (stringp title))))
  (concatenate 'string
    "<a href='https://www.lispworks.com/documentation/HyperSpec/"
    (or url "")
    "'>"
    title
    "</a>"))
other
(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>")
other
(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 built-in ACL2 functions (see @(see
 acl2-built-ins)) may wish to import symbols into their package from the large
 list @(tsee *acl2-system-exports*).</p>

 @(`(:code *acl2-exports*)`)")
other
(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*)`)")
other
(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>")
other
(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>")
other
(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>")
other
(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 +)")
other
(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 -)")
other
(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 /)")
other
(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 /=)")
other
(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+)")
other
(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-)")
other
(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'). Thus, the following are theorems.</p>

 @({
  (thm (equal (< (fix x) y) (< x y)))
  (thm (equal (< x (fix y)) (< x y)))
 })

 <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>")
other
(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 <=)")
other
(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 =)")
other
(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 >)")
other
(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 >=)")
other
(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>")
other
(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 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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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 of @(tsee ld), see @(tsee
 p!).  However, @('p!') behaves differently if you're typing to the interactive
 break caused by @(see break-rewrite).  Instead of popping up one level,
 @('p!') in break-rewrite prints a message and is otherwise a no-op.</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>")
other
(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>")
other
(defxdoc abort-soft
  :parents (miscellaneous)
  :short "Control how interrupts are handled in proofs"
  :long "<p>ACL2 arranges by default that when a proof is interrupted (with
 @('Control-C')), a ``soft'' abort occurs in the following sense: the message
 below is printed and then the proof attempt continues temporarily before
 ultimately failing (usually very soon thereafter).</p>

 @({
 ***********************************************
 Note:  interrupt signal
   Will attempt to exit the proof in progress;
   otherwise, the next interrupt will abort the proof.
   For an immediate abort see :DOC abort-soft.
 ***********************************************
 })

 <p>This default behavior supports proper operation of the utility, @(tsee
 redo-flat), when a proof is interrupted.  It also supports more complete
 summaries than would be obtained with an immediate abort.  If you nevertheless
 want proofs to abort immediately, you may evaluate the form @('(assign
 abort-soft nil)').  To restore the default behavior, evaluate @('(assign
 abort-soft t)').</p>

 <p>Remarks for system hackers.</p>

 <ul>

 <li>An important effect of having evaluated @('(assign abort-soft nil)') is
 that an interrupt will send you immediately back to the ACL2 read-eval-print
 loop, in contrast to the default behavior where the prover returns an @(see
 error-triple) whose error component is non-@('nil').</li>

 <li>It may be preferable to bind @(see state) global @('abort-soft') rather
 than to assign it globally.  See the implementation of @(see
 prove$) (specifically, the definition of @('prove$-fn') in @(see
 community-book) @('books/tools/prove-dollar.lisp')) for an example.</li>

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

 <p>This manual contains <see topic='@(url installation)'>installation
 instructions</see>, <see topic='@(url acl2-tutorial)'>tutorials</see>, and
 @(see acknowledgments), as well as information about <see topic='@(url
 mailing-lists)'>mailing lists</see>, related @(see publications), and <see
 topic='@(url workshops)'>ACL2 Workshops</see>.</p>

 <p>See @(see documentation) for how to access the ACL2+Books User's Manual.
 See @(see releases) for information about past ACL2 releases.  See the <a
 href='http://www.cs.utexas.edu/users/moore/acl2/'>ACL2 home page</a> for other
 information, including seminars.</p>

 <p>For statistics on ACL2 code size, see file @('doc/acl2-code-size.txt').</p>")
other
(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)")
other
(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>")
other
(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 t).

  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), @(see
 with-brr-data), and @(see dmr).</p>

 <p>Accumulated persistence tracking can be turned on or off.  It is generally
 off.  When on, proofs may take a little more time than otherwise.  (We
 measured approximately 11% more time in a so-called ``everything'' regression
 run in May 2020.)  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>We do not claim that tracking of runes for accumulated-persistence is
 perfect.  In practice, we believe it is quite reliable with the exception of
 @(see congruence) runes and, in some cases @(see executable-counterpart)
 runes. (For the latter, details are in a comment in the ACL2 source definition
 of function @('print-useless-runes').)</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>See @(see useless-runes) for a way to speed up proofs by automatically
 turning off useless rules.</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 <see topic='@(url type-reasoning)'>type reasoning</see>,
 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>")
other
(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'' @(see rune)
 application attempts, and we describe how ``useless'' rune application
 attempts can actually be critical for a proof's success.  We conclude with a
 few words about counting frames when there are nested (recursive) applications
 of a rune.</p>

 <p><i>Overcounting of ``useful'' 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><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>

 <p>Finally we discuss accumulation into frame counts in the case of a nested
 (recursive) application of a rule: that is, the case that during the
 application of a rule, the rule is applied again &mdash; in particular, while
 relieving a hypothesis or rewriting the right-hand side from the original rule
 application.  Recall that the implementation of @(see accumulated-persistence)
 keeps a stack of @(see rune)s currently being applied; thus, we are
 considering here the case that a rune is pushed onto a stack on which it
 already resides.  In that case, we count tries as usual but we avoid
 accumulating until we reach the outermost (topmost) application of that rune.

 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 theorem @('(mem a (list 1 2 3 a))').  Each time
 the definition of @('mem') is applied, a new stack frame is pushed.  We avoid
 accumulating into the @(':frames') count for that stack frame unless it is the
 topmost stack frame for that definition.  Otherwise the final @(':frames')
 count would be the sum of the counts for those individual frames, which form a
 linear sequence whose sum would therefore be quadratic in the number of
 applications of the definition of @('mem').</p>")
other
(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>Collins Aerospace</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>Intel</li>

 <li>Kestrel Institute</li>

 <li>Kestrel Technology</li>

 <li>NSF (see below)</li>

 <li>ONR</li>

 <li>SRC</li>

 <li>Sun Microsystems</li>

 <li>U.S. Army, in particular ARL</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>Regarding DARPA support: We thank DARPA for approving release of the
 following documentation topics and support with &ldquo;DISTRIBUTION
 STATEMENT A. Approved for public release. Distribution is
 unlimited.&rdquo;</p>

 <ul>

  <li>@(see Recursion-and-induction) together with its subtopics and its answer
      key (@(see community-books) files @('demos/r-and-i-answer-key-input.lsp')
      and @('demos/r-and-i-answer-key-log.txt'))</li>

  <li>@(see Gentle-introduction-to-ACL2-programming)</li>

  <li>@(see Loop$-primer) together with its subtopics and its answer key
      (@(see community-books) files @('lp6.lisp'), @('lp8.lisp'),
      @('lp12.lisp'), @('lp14.lisp'), @('lp17-11-lemma2.lisp'), and
      @('lp17.lisp'))</li>

  <li>@(see Start-here)</li>

 </ul>

 <p>Regarding NSF support:</p>

 <ul>

  <li>This material is based upon work supported by the National Science
      Foundation under Grant Nos. CCF-1526760, CNS-1525472, CCF-1153558,
      EIA-0303609, CNS-0429591, ISS-0417413, CCF-0945316, and CNS-0910913.</li>

  <li>Any opinions, findings and conclusions or recommendations expressed in
      this material are those of the authors and do not necessarily reflect the
      views of the National Science Foundation.</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>ACL2 depends on the availability of robust Common Lisp implementations, so
 we are grateful to the developers of those implementations.  Early in ACL2's
 history, 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.  Gary Byers and R. Matthew Emerson have continually improved
 Clozure Common Lisp (CCL), often based on feedback from the ACL2 community.
 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>Other contributions to the ACL2 system continue to be made by members of the
 ACL2 community.  In particular, following the first Developers Workshop in
 May, 2017 through the time of this writing in November, 2019, such
 contributors include Alessandro Coglio, Keshav Kini, Mihir Mehta, Pete
 Manolios, and especially Sol Swords, while Eric Smith and many others have
 suggested changes that we have implemented, often by providing helpful
 examples.  The @(see release-notes) detail such contributions as well as many
 suggestions from the community for improvements that we ultimately
 implemented.</p>

 <p>We also thank the contributors to the ACL2 @(see 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>

 ")
other
(defxdoc acl2
  :parents (top)
  :short "ACL2 system documentation"
  :long "<p>Those topics that pertain to the ACL2 system belong under this node
 of the @(see documentation).  See @(see top) for the top node of this manual,
 under which may be found many topics pertaining to the @(see
 community-books).</p>")
other
(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>")
other
(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>")
other
(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>")
other
(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
 symbols)'>here</see> <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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 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>

 ")
other
(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>If you are already familiar with Common Lisp (or even some other Lisp
 variant), then you may find it helpful to start with the topic, @(see
 introduction-to-programming-in-acl2-for-those-who-know-lisp).</p>

 <p>See any documentation for Common Lisp for more details on many of these
 functions.</p>")
other
(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)")
other
(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 except that any settings of @(tsee
 ld) specials are remembered once this call of @(tsee ld) has completed other
 than @(tsee ld-error-action), which will always be @(':command-conventions')
 after that call of @('ld') completes.  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)) except that
 @(':ld-error-action') is @(':error').  If an error is encountered, then no
 subsequent forms in the file will be evaluated and ACL2 will quit
 immediately.</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>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>

 <h3>Silent loading of ACL2 customization files</h3>

 <p>When the environment variable @('ACL2_CUSTOMIZATION_QUIET') is set and not
 @('""'), there will generally be no output from ACL2 customization.  A
 special value of @('"all"') for this variable will cause continued minimal
 output after startup, as explained in the following remark.</p>

 <p>Technical Remark.  For quiet loading of acl2-customization files, @(tsee
 ld) specials are bound to the following values.</p>

 @({
 ld-verbose = nil
 ld-pre-eval-print = :never
 ld-post-eval-print = nil
 ld-prompt = nil
 })

 <p>These @('ld') specials are returned to their normal values after loading an
 ACL2 customization file, with one exception: if @('ACL2_CUSTOMIZATION_QUIET')
 has value @('"ALL"') (or @('"all"'); the case is irrelevant), then those
 values are retained in the ACL2 loop even after customization completes.</p>")
other
(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 3 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 @(see type-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.  It need not associate a value with
 @(':SYSTEM'), to denote the @('books/') directory (see @(see community-books);
 see @(see include-book), in particular the section on ``Books Directory.''
 Also see @(tsee add-include-book-dir), @(tsee add-include-book-dir!), and
 @(tsee project-dir-alist).</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>

 @({
  :subgoal-loop-limits
 })

 <p>This key's value must be a @(tsee cons) whose @(tsee car) is either
 @('nil') or a natural number and whose @(tsee cdr) is @('nil') or a natural
 number.  See @(see set-subgoal-loop-limits).</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>

 @({
  :in-theory-redundant-okp
 })

 <p>When this key's value is @('t'), an @(tsee in-theory) event may be
 redundant.  See @(tsee set-in-theory-redundant-okp).</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>")
other
(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>Note: If you are not happy with the way text is displayed with ACL2-Doc,
 see @(see xdoc::terminal).</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 into Emacs the distributed file
 <tt>acl2-doc.el</tt> from an appropriate directory; see @(see emacs).  This
 will happen automatically if you load <tt>emacs-acl2.el</tt> from an
 appropriate directory; again, see @(see emacs).  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!
  Shift-<Return>  acl2-doc-go!-new-buffer
  g               acl2-doc-go
  G               acl2-doc-go-new-buffer
  h               acl2-doc-help
  ?               acl2-doc-summary
  i               acl2-doc-index
  ,               acl2-doc-index-next
  <               acl2-doc-index-previous
  K               acl2-doc-kill-buffers
  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
  <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).

  Shift-<Return>  acl2-doc-go!-new-buffer
     Go to the topic occurring at the cursor position in a new buffer.  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).  The new
     buffer's name reflects that topic name, but it stays the same even if the
     topic is subsequently changed there.

  g             acl2-doc-go
     Go to the specified topic; performs completion.  The new buffer's name
     reflects that topic name, but it stays the same even if the topic is
     subsequently changed there.

  G             acl2-doc-go-new-buffer
     Go to the specified topic in a new buffer; performs completion.

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

  ?             acl2-doc-summary
     Go to the ACL2-Doc-summary topic for one-line summaries of ACL2-Doc
     browser commands.

  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.  Also note
     that this command is buffer-local; it will follow the most recent i
     command executed in the current ACL2-Doc buffer.

  <             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.  Also note that this command is
     buffer-local like the "," command.

  l             acl2-doc-last
     Go to the last topic visited in the current buffer.  This command is
     buffer-local.

  n             acl2-doc-search-next
     Find the next occurrence for the most recent search or regular expression
     search.  Note that this command is buffer-local; it will follow the most
     recent search initiated in the current buffer.

  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, and this command is buffer-local.

  q             acl2-doc-quit
     Quit the current ACL2-Doc buffer.

  K             acl2-doc-kill-buffers
     Kill all background ACL2-Doc buffers.  If invoked in an ACL2-Doc buffer,
     all ACL2-Doc buffers except the current one will be killed.  If invoked in
     any other buffer, all ACL2-Doc buffers will be killed.  With prefix
     argument, avoid a query that asks for confirmation.

  r             acl2-doc-return
     Return to the last topic visited in the current buffer, popping the stack
     of such topics.  This command is buffer-local.

  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.

  <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.  If this fails,
     evaluate Emacs variable acl2-doc-download-error for information on
     how to perform the download without Emacs.

  H             acl2-doc-history
     Visit a buffer that displays the names of all topics visited (in any
     ACL2-Doc buffer) 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"
  "https://acl2.org/doc/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 tips:<p/>

 <ul>

 <li>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 ?>').</li>

 <li>To find completions that have package prefixes, type a colon (:) in the
 front, and completion will show matching topics.  For example, @('"g"')
 followed by @('":rew"') and then two tabs will show, at least in recent
 versions of Emacs, a list of topics that includes
 @('"ACL2-PC::REWRITE"').</li>

 </ul><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='https://acl2.org/doc/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>")
other
(defxdoc acl2-doc-summary
  :parents (documentation)
  :short "Summary of @(see acl2-doc) commands"
  :long "<p>See @(see acl2-doc) for information about the custom Emacs browser
  for viewing ACL2 @(see documentation).  In the present topic we list the
  commands with extremely abbreviated documentation: only a single line for
  each.  For even briefer summaries, you can use the standard Emacs command,
  @('Control-h m').</p>

 @({
    <Return>      acl2-doc-go!
       Go to the topic occurring at the cursor position.
    Shift-<Return>  acl2-doc-go!-new-buffer
       Go to the topic occurring at the cursor position in a new buffer.
    g             acl2-doc-go
       Go to the specified topic; performs completion.
    G             acl2-doc-go-new-buffer
       Go to the specified topic in a new buffer; performs completion.
    h             acl2-doc-help
       Go to the ACL2-Doc topic to read about how to use the ACL2-Doc browser.
    ?             acl2-doc-summary
       Go to the ACL2-Doc-summary topic for one-line summaries of commands.
    i             acl2-doc-index
       Go to the specified topic or else one containing it as a substring.
    ,             acl2-doc-index-next
       Continue to the next topic for the most recent i command.
    <             acl2-doc-index-previous
       Return to the preceding topic for the most recent i command.
    K             acl2-doc-kill-buffers
       Kill all background ACL2-Doc buffers.
    l             acl2-doc-last
       Go to the last topic visited.
    n             acl2-doc-search-next
       Find the next occurrence for the most recent search.
    p             acl2-doc-search-previous
       Find the previous occurrence for the most recent search.
    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 for the input string (with prefix arg: under a given topic).
    S             acl2-doc-re-search
       Regular-expression search (with prefix arg: under a given topic).
    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 and manual name in the minibuffer.
    SPC           scroll-up
       Scroll up (same as Control-v)
    TAB           acl2-doc-tab
       Visit the next link on the current page.
    <backtab> (which often is Shift-TAB): acl2-doc-tab-back
       Visit the previous link on the current page.
    D
       Download the manual from the web; then restart ACL2-Doc.
    H             acl2-doc-history
       Visit the History buffer, with names of all visited topics in order.
    I             acl2-doc-initialize
       Restart ACL2-Doc.  With a prefix argument, choose which manual.
    /             acl2-doc-definition
    Control-t /   acl2-doc-definition
       Find an ACL2 definition (in analogy to built-in Emacs command meta-.).
    W             acl2-doc-where-definition
       Find an ACL2 definition, with default from current page's topic.
 })")
other
(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>

 <p>The following mailing list pages include links to their archives.</p>

 <ul>

 <li>acl2-help list:<br/>
 <tt><a
 href='https://utlists.utexas.edu/sympa/info/acl2-help'>https://utlists.utexas.edu/sympa/info/acl2-help</a></tt></li>

 <li>acl2 list:<br/>
 <tt><a
 href='https://utlists.utexas.edu/sympa/info/acl2'>https://utlists.utexas.edu/sympa/info/acl2</a></tt></li>

 </ul>")
other
(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)")
other
(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>")
other
(defxdoc acl2-sedan
  :parents (acl2-tutorial)
  :short "ACL2 Sedan interface"
  :long "<p>Many successful ACL2 users run in a 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 ACL2 Sedan 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 distributed with the
 ACL2 community books in @('books/acl2s/distribution/acl2s-hooks/').  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>")
other
(defxdoc acl2-tutorial
  :parents (start-here about-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='https://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='https://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>")
other
(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>")
other
(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 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>")
other
(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)")
other
(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>")
other
(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>")
other
(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>")
other
(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 @(see 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 @(see summary)
 but nevertheless changes the ACL2 logical @(see world) and is so
 recorded.</p>")
other
(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 @(see 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 hint 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>")
other
(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>")
other
(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>")
other
(defxdoc add-global-stobj
  :parents (events stobj)
  :short "Add a global @(see stobj) with a given name"
  :long "<p>See @(see stobj) for background on stobjs, and see @(see defstobj)
 and @(see defabsstobj) for further background.</p>

 <p>We start with the General Form and an Example Form, which are followed by
 discussions of global stobjs and the effect of this utility.</p>

 @({
 General Form:
 (add-global-stobj x state)
 })

 <p>where @('x') evaluates to the name of a stobj that does not already have a
 global value, either because it was introduced by @(tsee defstobj) or @(tsee
 defabsstobj) with keyword value @(':non-executable t') or because @(tsee
 remove-global-stobj) was previously applied to that name.</p>

 @({
 Example Form:
 (add-global-stobj 'st state) ; st non-global from defstobj or defabsstobj
 })

 <p>By default, @('defstobj') and @('defabsstobj') create a &ldquo;live&rdquo;,
 mutable object for the given name that can be referenced at the top level,
 which we call a &ldquo;global&rdquo; stobj.  This is illustrated by the
 following log.</p>

 @({
 ACL2 !>(defstobj st fld)

 Summary
 Form:  ( DEFSTOBJ ST ...)
 Rules: NIL
 Time:  0.02 seconds (prove: 0.00, print: 0.00, other: 0.02)
  ST
 ACL2 !>st ; global stobj for the name, ST
 <st>
 ACL2 !>(fld st)
 NIL
 ACL2 !>(update-fld 3 st)
 <st>
 ACL2 !>(fld st)
 3
 ACL2 !>
 })

 <p>However, the following log shows that we can introduce a stobj without
 creating a global stobj, by using the keyword value @(':non-executable
 t').</p>

 @({
 ACL2 !>(defstobj st2 fld2 :non-executable t)

 Summary
 Form:  ( DEFSTOBJ ST2 ...)
 Rules: NIL
 Time:  0.02 seconds (prove: 0.00, print: 0.00, other: 0.02)
  ST2
 ACL2 !>(fld2 st2)


 ACL2 Error [Evaluation] in TOP-LEVEL:  Unbound var ST2.  Note that
 ST2 is a non-executable stobj.

 ACL2 !>
 })

 <p>The function @('add-global-stobj') creates a global stobj for a given stobj
 name when one does not already exist.  Let's continue the log started
 immediately above.</p>

 @({
 ACL2 !>(add-global-stobj 'st2 state)
  ST2
 ACL2 !>(fld2 st2)
 NIL
 ACL2 !>(update-fld2 3 st2)
 <st2>
 ACL2 !>(fld2 st2)
 3
 ACL2 !>
 })

 <p>The function @('remove-global-stobj') removes the indicated global stobj.
 We continue the log above.</p>

 @({
 ACL2 !>(remove-global-stobj 'st2 state)
  ST2
 ACL2 !>(fld2 st2)


 ACL2 Error [Evaluation] in TOP-LEVEL:  Unbound var ST2.  Note that
 ST2 is a non-executable stobj.

 ACL2 !>
 })

 <p>If we remove a global stobj, as shown just above, and then add the
 corresponding global stobj, we get a fresh copy of that stobj; all previous
 updates are discarded.</p>

 @({
 ACL2 !>(add-global-stobj 'st2 state)
  ST2
 ACL2 !>(fld2 st2)
 NIL
 ACL2 !>
 })")
other
(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 to "foo" the absolute
 ; directory pathname "/u/smith/":
 (add-include-book-dir :smith "/u/smith/")

 ; For (include-book "bar" :dir :util), prepend to "bar" the absolute
 ; directory pathname corresponding to the interpretation of "utilities/"
 ; with respect to the current connected-book-directory (cbd):
 (add-include-book-dir :util "utilities")

 ; For (include-book "lib/floor-mod/top" :dir :arith), prepend to
 ; "lib/floor-mod/top" the string "<dir>/arithmetic-5/" where "<dir>"
 ; is the community books directory pathname string:
 (add-include-book-dir :arith (:system . "arithmetic-5"))
 })

 <p>Note: This is an event!  It does not print the usual event @(see 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') represents a directory:
 either a relative or absolute @(see pathname) string or a @(see sysfile).  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) and @(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, when a relative pathname is supplied, 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>See @(tsee project-dir-alist) for another way to associate keywords with
 directory names, to take place only at the time ACL2 starts up.  Note that a
 keyword bound in the @('project-dir-alist') may also be bound by
 @('add-include-book-dir'), but only if both bindings are to the same
 directory.</p>

 <p>The keyword @(':system') can never be redefined.  It will always point to
 the absolute pathname of the @(see community-books) directory, which by
 default is the subdirectory @('"books/"') of the directory where the ACL2
 executable was 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 @(tsee
 acl2-defaults-table) and thus is automatically @(see local) to the book or
 @(tsee encapsulate) event in which it occurs (and, it is thus illegal to call
 @('add-include-book-dir') in an explicitly @(tsee local) context).  See @(tsee
 add-include-book-dir!) for a corresponding non-@(tsee local) event.</p>

 <p>As with @(tsee add-include-book-dir!), direct table updates are disallowed;
 you must use @('add-include-book-dir') to add to the @('acl2-defaults-table')
 and @(tsee delete-include-book-dir) to remove from it.</p>")
other
(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>This topic assumes familiarity with @(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 @(see 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>See @(tsee project-dir-alist) for another way to associate keywords with
 directory names, to take place only at the time ACL2 starts up.  Note that a
 keyword bound in the @('project-dir-alist') may also be bound by
 @('add-include-book-dir!'), but only if both bindings are to the same
 directory.</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>")
other
(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 such
 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>")
other
(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 add-macro-fn) and @(see add-binop) for extensions of this utility
 that also affect printing.</p>

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

 <p>where @('macro-name') is a macro name and @('sym') is a symbol.  If
 @('sym') is a function symbol, then this event establishes @('macro-name') as
 a <i>macro-alias</i> for @('sym') by associating @('macro-name') with @('sym')
 in the @(see table), @('macro-aliases-table'); see @(see macro-aliases-table)
 for detailed discussion.  In particular, that discussion explains the use of
 macro-aliases to allow a macro name as the second argument of
 @('add-macro-alias'), as in the example below.</p>

 @({
 (defun fn (x) x)
 (defmacro mac1 (x) (fn x))
 (defmacro mac2 (x) (list 'mac1 x))
 (add-macro-alias mac1 fn); or (table macro-aliases-table 'mac1 'fn)

 ; The following is equivalent to (add-macro-alias mac2 fn), since
 ; mac1 is a macro-alias for fn by virtue of the preceding event.
 ; Note that the form (table macro-aliases-table 'mac2 'mac1)
 ; would not suffice here; that is, the in-theory event below would cause an
 ; error, because mac1 is not a function symbol.
 (add-macro-alias mac2 mac1)

 ; Success:
 (in-theory (disable mac2))
 })

 <p>Also see @(see macro-aliases-table) and also see @(see
 remove-macro-alias).</p>")
other
(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>")
other
(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 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 @(see 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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(defxdoc advanced-features
  :parents (acl2-tutorial programming)
  :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), @(see ADD-INCLUDE-BOOK-DIR!), and @(see
 PROJECT-DIR-ALIST) 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>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 INDUCTION-COARSE-V-FINE-GRAINED) for a discussion of how a
 well-chosen setting for @(see RULER-EXTENDERS) can improve an induction
 scheme, especially for a function containing @(tsee let) and @(tsee let*)
 bindings that contain conditional recursive calls.</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), see
 @(see SET-INHIBIT-ER), 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 and, optionally, clausal form for goals.</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>

 <li>See @(see WITH-BRR-DATA) for finding the source of a term in prover
 output.</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) and @(see MACROLET) to provide local binding of function
 and macro names.</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 @(see multiple-value) result to a
 single-value 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 @(see 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>

 ")
other
(defxdoc alist-keys-subsetp
  :parents (alists acl2-built-ins)
  :short "Check that all keys of the alist belong to a given set"
  :long "<p>The call @('(alist-keys-subsetp alist keys)') returns @('t') when
 each key of the given alist belongs to the given list of keys; else it returns
 @('nil').  This is Boolean-equivalent to @('(subsetp-eq (strip-cars alist)
 keys)'), but it avoids consing up the keys of @('alist').</p>")
other
(defxdoc alist-to-doublets
  :parents (alists acl2-built-ins)
  :short "Convert an alist to a list of two-element lists"
  :long "<p>The call @(call alist-to-doublets) returns 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.</p>

 @({
 (implies (and (natp i) (< i (len alist)))
          (equal (nth i (alist-to-doublets alist))
                 (let ((pair (nth i alist)))
                   (list (car pair) (cdr pair)))))
 })")
other
(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)")
other
(defxdoc alists
  :parents (programming)
  :short "Operations on association lists, which bind keys to values.")
other
(defxdoc allegro-cl
  :parents (obtaining-common-lisp)
  :short "Allegro Common Lisp as a host for ACL2"
  :long "<p><a href='https://franz.com/products/allegro-common-lisp/'>Allegro
 Common Lisp</a> (Allegro CL) is one of the Common Lisp implementations upon
 which an ACL2 executable can be built (see @(see obtaining-common-lisp)).  But
 here, we discuss a concern.</p>

 <p>Although testing is ongoing for ACL2 built upon Allegro CL, the version
 used has been Allegro CL 10.1 since 2017.  What's more, in September 2025, for
 an ACL2 executable built with host Lisp Allegro CL, the use of &ldquo;@('make
 regression')&rdquo; resulted in four books (in the @(see community-books))
 that failed to certify.  We discuss those failures in the
 &ldquo;<b>Details</b>&rdquo; section below.  These failures may suggest that
 Allegro CL, at least for its Version 10.1, does not correctly support the
 Common Lisp language, or at least there is problematic ACL2 code specific to
 Allegro CL.  In practice we don't expect a lot of problems when using ACL2
 built on Allegro CL.  However, since Allegro CL is relatively slow compared to
 several other Common Lisp implementations that can host ACL2 &mdash; SBCL,
 CCL, LispWorks, and GCL &mdash; those failures suggest that Allegro CL might
 not be a good choice for ACL2 users.</p>

 <h3>Details</h3>

 <p>Here are details regarding the four certification failures under
 @('books/') that are referenced above.  <b>These details are quite technical
 and probably only of interest to system implementors.</b></p>

 <ul>

 <li>@('kestrel/c/syntax/validator.lisp')<p/>

 <p>The following error from the corresponding @('validator.cert.out') file is
 very surprising, since the @(tsee defrec) form for
 @('ACL2::CLAUSE-PROCESSOR-HINT') has a &ldquo;cheap&rdquo; flag of @('nil'),
 so the same error can be expected to show up regardless of the host Lisp
 &mdash; yet as of this writing (in September 2025) it seems not to have shown
 up for a long time, if ever.</p>

 @({
 HARD ACL2 ERROR in ACL2::RECORD-ERROR:  An attempt was made to treat
 (49683 :TYPE-PRESCRIPTION BLOCK-ITEM-TYPES) as a record of type
 ACL2::CLAUSE-PROCESSOR-HINT.
 })

 <p>There were other errors like that one as well.</p>

 <p>So for that same ACL2 version (ACL2 git hash
 fe29908c4589c1de3b41d6c98cc8bec012c7eba3), the same book and the books that
 (recursively) support it were certified using a safety-3 ACL2 executable built
 on CCL.  The book certified without any &ldquo;HARD ACL2 ERROR&rdquo;.  This
 suggests that the problem is likely restricted to runs using Allegro CL.</p>

 <p>However, that book allows some trust tags (in file @('cert.acl2') in that
 directory), so perhaps there are shenanigans that somehow exonerate the
 Allegro CL build of ACL2.  But the last failure discussed below does not
 involve trust tags.</p>

 </li>

 <li>@('kestrel/axe/examples/aes-blast.lisp')<br/>
 @('kestrel/axe/examples/aes-blast-boolean.lisp')<p/>

 <p>These two report errors (in their @('.cert.out') files) that involve using
 the @(see serialize) capability to write the @('.cert') file.  But
 @('cert.acl2') in that directory allows trust tags, which could be relevant.
 Note that serialize errors may be very difficult to debug.</p>

 <p>A second certification was tried on the second of these (picked
 arbitrarily) in case this was just a weird glitch.  However, a similar error
 occurred (though with a slightly different backtrace).</p>

 </li>

 <li>@('projects/aleo/vm/circuits/axe/blake2s-proof2.lisp')<p/>

 <p>This one shows a backtrace that includes the following form.</p>

 @({
 (RATIONALP 8444461749428370424248824938781546531375899335154063827935233455916872368129)
 })

 <p>That shouldn't cause an error, but apparently it did.  Maybe the image was
 already corrupted.  Submitting that form in a fresh session produced no
 error.</p>

 <p>As with the first example, a safety-3 CCL-based certification (of this book
 and all supporting books, recursively) produced no errors.  But unlike the
 first example, this book does not allow trust tags.  This example thus
 provides strong evidence that Allegro CL is not a great choice for hosting
 ACL2.</p>

 </li>

 </ul>")
other
(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), versions preceding 2.7, 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 (again, for versions preceding 2.7) 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 a GCL
 version preceding 2.7, it has no side effect other than to print a message.
 This function always returns @('nil').</p>

 <p>In GCL versions starting with 2.7.0, allocation for the table would
 generally be a no-op other than to waste space, which is why
 @('allocate-fixnum-range') is a no-op for those versions.</p>")
other
(defxdoc alpha-char-p
  :parents (characters acl2-built-ins)
  :short "Recognizer for alphabetic characters"
  :long "<p>@('(Alpha-char-p x)') is true for a 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') states that its argument is a
 character.</p>

 <p>@('Alpha-char-p') is a Common Lisp function.  See any Common Lisp
 documentation for more information.  Note that the value returned may depend
 on the host Lisp; see @(see soundness), specifically Example 1 in the Section,
 &ldquo;Examples of divergence among Lisp implementations&rdquo;.</p>

 @(def alpha-char-p)")
other
(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)")
other
(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 @(see 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), while
  accommodating (MY-APP X Y).

  These suggestions were produced using the :induction rules LEN and
  MY-APP. 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.
  When applied to the goal at hand the above induction scheme produces
  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 @(see 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>")
other
(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)")
other
(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='https://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='https://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='https://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='https://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='https://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))))
 })")
other
(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 (@('nil')-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)")
other
(defxdoc apply$
  :parents (acl2-built-ins programming)
  :short "Apply a badged function or tame lambda to arguments"
  :long "<p>We recommend that you read the paper <a
  href='https://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 for both motivation and foundational details.  You might
  also read @(see introduction-to-apply$)!</p>

  <p>This documentation starts with a <b>glossary</b> of terms.  Then we
  provide some <b>examples</b> and present the <b>specification</b> of
  @('apply$').  Next, we deal with issues related to @('apply$') in
  <b>definitions</b>, <b>stating and proving theorems</b>, <b>guards and guard
  verification</b>, and <b>top-level evaluation</b>.  Finally we exhibit the
  <b>formal definitions</b> @('apply$') and some related concepts.  We have
  sprinkled in a little tutorial material for readability but have not provided
  much motivation for some design decisions.</p>

  <h3>Glossary</h3>

  <p>Here is a brief glossary of terms used in the semantics of @('apply$').
  While we provide links to the documentation of the concepts, we urge you not
  to follow those links until you've understood the big picture!</p>

  <ul>

  <li>@('apply$') &mdash; the ACL2 function that takes two arguments, one
      representing a function and the other listing actuals to be fed to that
      function.  Under certain conditions, @('apply$') applies the function to
      the arguments and returns the result.  @('Apply$') is mutually recursive
      with @(tsee apply$-lambda), @(tsee ev$), and @(tsee ev$-list).
      @('Apply$')'s ``badge'' (see below) is @('(APPLY$-BADGE 2 1 :FN NIL)')
      its arity is 2, its ``out arity'' is 1 (i.e., it returns 1 result), its
      first argument has ``ilk'' @(':FN') and is thus treated as a
      ``function;'' its second argument has ilk @('NIL') and is thus treated as
      an ordinary object.</li>

  <li>@(tsee badge) &mdash; an object associated with some function symbols
      indicating that @('apply$') can ``handle'' them and under what
      conditions.  The badge of a function symbol specifies its arity, its
      ``out arity,'' (i.e., the number of results the function returns), and
      the @(see ilk) of each argument position telling @('apply$') how each
      argument is treated.  The ilks are @(':FN'), @(':EXPR') and @('NIL').
      The association between a non-primitive function symbol and its badge is
      managed by @(tsee warrant)s.  In proofs, @('apply$') must have a warrant
      for every non-primitive function symbol to be applied.  Those warrants
      are provided as hypotheses to the theorem being proved.  Symbols without
      badges cannot be @('apply$')d.  Badges are generated, when possible, by
      @(tsee defwarrant).  (Badges can be generated for @(':')@('program') mode
      functions by @(tsee defbadge), allowing @('apply$') to handle such
      functions in top level evaluation not in proofs.)  Not every function
      symbol can have a badge.</li>

  <li>compiled @('LAMBDA') cache (or simply <i>cache</i> in this context) &mdash; a
      cache in the raw Lisp under ACL2 that supports the application of
      @('apply$') on well-formed, guard verified @('LAMBDA') objects.  Later in
      this Glossary we define ``lambda expression,'' ``@('LAMBDA') object,''
      and ``lambda$ expression'' &mdash; three similar looking phrases with very
      different meanings.  See @(tsee print-cl-cache) for some details of the
      cache.</li>

  <li>evaluation theory &mdash; the logical theory in which expressions
      submitted at the top level of the ACL2 read-eval-print loop are
      evaluated.  The evaluation theory is a consistent extension of the proof
      theory, the latter being the logical theory in which the ACL2 theorem
      prover operates.  The evaluation theory was introduced in ACL2 when
      @(tsee defattach) was added, but it was changed with the introduction of
      @('apply$').  All @(tsee warrant)s introduced by @('defwarrant') are
      assumed true in the evaluation theory but not in the proof theory.  This
      means ACL2 can execute calls of @('apply$') that arise in the evaluation
      of top-level input, but ACL2 cannot evaluate all calls of @('apply$')
      that arise in proofs unless the appropriate warrants are available as
      hypotheses.  See @(see guarantees-of-the-top-level-loop) for some details
      of the evaluation theory and how it differs from the proof theory
      supported by the ACL2 theorem prover.</li>

  <li>lambda expression &mdash; an integral part of ACL2's formal term syntax,
      lambda expressions are the way @('let') expressions and other
      variable-binding idioms are translated into formal terms.  Lambda
      expressions have nothing to do with @('apply$')!  See @(see lambda) for a
      discussion of three confusingly similar but different concepts: lambda
      expressions, @('LAMBDA') objects, and @('lambda$') expressions.  Read
      carefully anytime you see the word ``lambda!''</li>

  <li>@('LAMBDA') object &mdash; an ACL2 list constant, typically of the form
      @('(LAMBDA vars body)') or @('(LAMBDA vars dcl body)') that may be used
      as a ``function'' by @('apply$').  @('Apply$') treats any @(tsee consp)
      object in its first argument position as though it were a @('LAMBDA')
      object.  But it only gives sensible meanings to @(see tame) @('LAMBDA')
      objects.  And only well-formed @('LAMBDA') objects are executed
      efficiently.  But well-formed @('LAMBDA') objects are hard to type by
      hand &mdash; there are many constraints to keep in mind to guarantee
      well-formedness.  See @(tsee well-formed-lambda-objectp) if you really
      want to see all the rules.  But that is generally unnecessary.  We
      <i>strongly</i> recommend not entering @('LAMBDA') objects as quoted
      constants, e.g., @(''(LAMBDA (X) (+ 1 X))') &mdash; which is actually
      ill-formed!  Instead, use @(tsee lambda$), as in @('(lambda$ (x) (+ 1
      x))').  See also @(see lambda) for some clarifications.</li>

  <li>@(tsee lambda$) expression &mdash; an ACL2 macro that allows you to enter
      quoted well-formed @('LAMBDA') objects into your terms by typing
      untranslated expressions that resemble lambda expressions.  The
      @('lambda$') expression @('(lambda$ (x) (+ 1 x))') essentially translates
      into the quoted @('LAMBDA') object @(''(LAMBDA (X) (BINARY-+ '1 X))').
      We say ``essentially'' because @('lambda$') always inserts a
      @('(DECLARE (IGNORABLE v1 ... vn))') listing every formal and tags the
      body with a @(tsee RETURN-LAST) form that indicates it came from a
      translated @('lambda$'). See also @(see lambda) for some
      clarifications.</li>

  <li>@(tsee scion) &mdash; a function that is ancestrally dependent on @('apply$').
      In the early days of @('apply$') we called scions ``mapping functions''
      but in the Lisp community that implies iteration over a list and scions
      are more general.  Of course, a function that iterates over a list
      @('apply$')ing a ``function'' to each element and collecting the results
      is an example of a scion.  But so is function that takes a ``function''
      and applies it in one special situation, e.g., as a test or base case.
      Any function ancestrally dependent on @('apply$') is a scion whether or
      not it takes a ``function'' as an argument or maps over a domain.</li>

  <li>@(see tame) &mdash; the class of functions that @('apply$') knows about; we
      actually talk about ``tame functions,'' ``tame @('LAMBDA') objects,'' and
      ``tame expressions.''  The last are expressions that are evaluable by an
      interpreter named @(tsee ev$) that is mutually-recursive with @('apply$').
      @('Apply$') cannot handle all definable functions: ACL2 is first order
      and if @('apply$') were able to ``handle'' certain functions the logic
      would be inconsistent.</li>

  <li>@(tsee warrant) &mdash; a 0-ary predicate associated with some user-defined
      function symbols that must be a hypothesis of any theorem whose proof
      involves ``expanding'' @('apply$') on such symbols; the warrant gives
      @('apply$') ``permission'' to expand if the arguments to which the
      function is applied are appropriately @(see tame).  The warrant for a
      function specifies the function's @(tsee badge) and how @('apply$')
      behaves on the function symbol.  Warrants (and badges) are computed and
      introduced by the @(tsee defwarrant) event.  Not all function symbols can
      be warranted.</li>

  </ul>

  <p>You will get a much better understanding of these concepts if you read the
  paper cited above.</p>

  <h3>Examples</h3>

  <p>To illustrate @('apply$') and some related concepts we need some
  user-defined functions.  We therefore imagine that the following events
  have been successfully admitted.</p>

  <p><b>We strongly recommend that you include the following book in any
  session in which you intend to use or reason about @('apply$').</b></p>

  @({
  (include-book "projects/apply/top" :dir :system)

  (defun$ sq (x) (* x x))

  (defun$ collect$ (fn lst)
    (if (endp lst)
        nil
        (cons (apply$ fn (list (car lst)))
              (collect$ fn (cdr lst)))))

  (defun$ foldr (lst fn init)
    (if (endp lst)
        init
        (apply$ fn
                (list (car lst)
                      (foldr (cdr lst) fn init)))))

  (defun$ russell (fn x)
    (not (apply$ fn (list x x))))
  })

  <p>Note: @('Collect$') is pre-defined in ACL2 because it is part of the
  support for the @(tsee loop$) statement.</p>

  <p>@('Collect$') and @('foldr') might informally be called ``mapping
  functions'' because they map a given function over some domain and accumulate
  the answers somehow.  They are useful examples of what we call <i>scions
  of</i> @('apply$') or simply <i>scions</i>: functions in which @('apply$') is
  ancestral, i.e., functions that call @('apply$') or call functions that call
  @('apply$'), etc.  @('Russell') is also a scion.  See @(see scion) for
  more.</p>

  <p>Here are some evaluations carried out at the top-level of the ACL2 loop
  after the events above.  Top-level evaluations take place in ACL2's
  evaluation theory (see the discussion of the semantics of @(tsee defattach)),
  which is an extension of the theory in which proofs are conducted.  Put more
  bluntly, the following evaluations won't be carried out in proofs unless you
  have the right hypotheses!</p>

  @({
  ACL2 !>(apply$ 'sq '(5))
  25

  ACL2 !>(collect$ 'sq '(1 2 3 4 5))
  (1 4 9 16 25)

  ACL2 !>(collect$ (lambda$ (x) (* x x)) '(1 2 3 4 5))
  (1 4 9 16 25)

  ACL2 !>(foldr '(1 2 3) 'cons '(4 5 6))
  (1 2 3 4 5 6)

  ACL2 !>(foldr '(1 2 3 4 5)
                (lambda$ (x y)
                  (cons (sq x) y))
                nil)
  (1 4 9 16 25)

  ACL2 !>(foldr '(1 2 3 4)
                (lambda$ (x y) (foldr y 'cons (list x)))
                nil)
  (4 3 2 1)

  ACL2 !>(russell 'natp 3)
  NIL

  ACL2 !>(russell 'consp 3)
  T
  })

  <p>@('Apply$') doesn't always work the way you might want!</p>

  @({
  ACL2 !>(let ((x 'russell))(russell x x))

  ACL2 Error in TOP-LEVEL:  The value of APPLY$-USERFN is not specified when
  the first argument, fn, is RUSSELL, and the second argument, args,
  is (RUSSELL RUSSELL).  Fn has badge (APPLY$-BADGE 2 1 :FN NIL) and
  args is not known to satisfy the tameness requirement of that badge.
  })

  <p> @(tsee Apply$-userfn) is the undefined function called by @('apply$')
  when it is asked to apply a user-defined function symbol instead of a builtin
  function symbol.  The @(tsee warrant) for @('russell') actually specifies the
  value of @('(apply$-userfn 'russell ...)')  under the @(tsee tame)ness
  requirements, and those requirements are violated above.  This is necessary
  to preserve the consistency of the logic.  Otherwise:</p>

  <code>
  (russell 'russell 'russell)
  = {by defun of russell}
  (not (apply$ 'russell (list 'russell 'russell)))
  =  {by the naive expectation that apply$ always ``works''}
  (not (russell 'russell 'russell))
  Contradiction!
  </code>

  <p>Top-level evaluation of @('apply$') expressions raises problems not seen
  anywhere else in ACL2's execution model: While executing syntactically legal
  terms the evaluator can encounter undefined functions or weirdly ill-formed
  terms not caught by the usual ACL2 translation mechanism.  The ACL2
  translation mechanism checks the well-formedness of @(tsee lambda$)
  expressions (and user-typed quoted @('LAMBDA') objects) that occur in
  positions of ilk @(':FN') and are therefore destined for @('apply$').  But
  the translation checks can be defeated.  The @('LAMBDA') object below
  contains a call of the undefined function @('foo') but the error is not
  caught at translation time; it is caught only when the form executed.</p>

  @({
  ACL2 !>(apply$ `(lambda (x) (foo x)) '(5))

  ACL2 Error in TOP-LEVEL:  The value of BADGE-USERFN is not specified
  on FOO because FOO is not a known function symbol.
  })

  <p>Note the <i>backquote</i> on the @('LAMBDA') object.  This defeats the
  check of well-formedness because the @('LAMBDA') object is not @('quote')d.
  We could have equally written</p>

  @({
  ACL2 !>(apply$ (list 'lambda '(x) (cons 'foo '(x))) '(5))
  })

  <p>with the same result.  There is nothing unsound about this.  @('Apply$')
  can take any objects as arguments.  But it won't always ``behave'' as you
  might expect.  One way to explore the edge cases of @('apply$') is to execute
  it on ill-formed input.  In addition, some theorems may require consing up a
  @('LAMBDA') object in terms of objects used elsewhere in the theorem.  See
  example theorem @('[3]') below.</p>

  <p>A peculiar aspect of @('LAMBDA') objects is that they can be written as
  legal ACL2 constants <i>before</i> they are well-formed @('LAMBDA') objects,
  e.g., by referring to undefined functions, @(':program') mode functions,
  unbadged functions, etc.  They are, after all, just arbitrary quoted objects
  and any value in ACL2 can be quoted.  But an ill-formed object can
  <i>become</i> well-formed if the world is appropriately extended, e.g., the
  appropriate @('defun')s, @('defbadge')s, and @('defwarrant')s are made.
  Perhaps worse, they can be well-formed and then <i>become</i> ill-formed by
  an undo.  So at runtime @('apply$') has to check that the function symbol or
  @('LAMBDA') object is appropriate.  There is a sophisticated cache behind the
  execution machinery for @('LAMBDA') objects in the evaluation theory.  See
  @(tsee print-cl-cache).</p>

  <p>Here are some theorems that can be proved about these concepts.  The last
  of the theorems shown below requires two lemmas, named
  @('weird-little-lemma1') and @('weird-little-lemma2'), shown in
  @('books/projects/apply/report.lisp').</p>

  <p>For a summary of how the rewriter handles @('apply$'), @('ev$'), and
  @('loop$') @(see scion)s, see @(see
  rewriting-calls-of-apply$-ev$-and-loop$-scions).</p>

  @({

  ; [1] SQ squares, if you have the warrant for sq!  Imagine for a moment that
  ; we could prove (equal (apply$ 'SQ (list i)) (* i i)) without the warrant
  ; hypothesis shown below.  And imagine that we did so in an encapsulated
  ; environment in which sq was locally defined to be (* x x).  Then imagine we
  ; exported the simpler theorem out of that encapsulate and defined sq to be
  ; (+ 1 (* x x)).  Then ACL2 would be unsound.  Exporting a theorem requires
  ; that the theorem be ancestrally independent of every locally defined
  ; function and the simpler hypothetical theorem is, because the symbol 'SQ is
  ; not ancestrally dependent on sq.  But ACL2 cannot prove the simpler
  ; theorem!  It cannot ``open'' apply$ on 'SQ without the warrant for sq and
  ; the warrant for sq is ancestrally dependent on sq.  So the theorem below
  ; cannot be exported from an environment in which sq is locally defined.
  ; Thus warrants solve the so-called ``LOCAL problem.''

  (thm (implies (warrant sq)
                (equal (apply$ 'SQ (list i))
                       (* i i))))

  ; [2] Collect$ distributes over append for any fn.

  (thm (equal (collect$ fn (append a b))
              (append (collect$ fn a)
                      (collect$ fn b))))

  ; [3] Foldr can be used to collect$, but the collection must
  ; be with an ``ok'' function (a tame function of one
  ; argument).  Note the backquote on the LAMBDA.  This is
  ; a theorem that requires us to cons up a LAMBDA object.

  (thm (implies (ok-fnp fn)
                (equal (foldr lst
                              `(LAMBDA (X Y) (CONS (,fn X) Y))
                              nil)
                       (collect$ fn lst))))
  })

  <h3>Specification of APPLY$</h3>

  <p><b>We strongly recommend that you include the following book in any
  session in which you intend to use or reason about @('apply$').</b></p>

  @({
  (include-book "projects/apply/top" :dir :system)
  })

  @({
  General Form:
  (apply$ fn args)
  })

  <p>where @('fn') is some function symbol or @('LAMBDA') object and @('args')
  is a true list.  Informally, @('apply$') applies the function named by the
  first argument to the appropriate number of elements taken from the second
  argument.  We might express this as:</p>

  <code>
  <b>Naive Specification (for a single-valued function):</b>
  (apply$ 'fn args) = (fn (nth 0 args) ... (nth (- n 1) args))

  <b>Naive Specification (for a multi-valued function):</b>
  (apply$ 'fn args) = (mv-list k (fn (nth 0 args) ... (nth (- n 1) args)))
  </code>

  <p>where @('fn') is of arity @('n') and @('k') is the ``out arity'' of
  @('fn') (the number of returned values).  <b>However</b>, these naive
  specifications are guaranteed only if either (i) @('fn') is a function symbol
  that has a @(tsee badge) and @('args') satisfies the @(see tame)ness
  requirements of the badge, or (ii) @('fn') is a well-formed @('LAMBDA')
  object that returns 1 result.  The tameness requirement is that if an element
  of @('args') is in an argument position of @('fn') with ilk @(':FN') then the
  element must satisfy @('tamep-functionp') and if the element is in an
  argument position of ilk @(':EXPR') it must satisfy @('tamep').  See @(tsee
  badge) for further discussion of condition (i).  As for (ii), rather than
  explain ``well-formed @('LAMBDA') object'' here we encourage you to write
  @(tsee lambda$) expressions when you want to @('apply$') a @('LAMBDA')
  object.</p>

  <p>The @(see ilk)s of @('apply$') are @(':FN') and @('NIL') respectively,
  telling us that @('apply$') treats its first argument as a ``function'' and
  its second as an ordinary object (never as a function).  Initially
  @('apply$') and several functions used in the translation of @('loop$')
  statements are the only symbols in ACL2 with an ilk of @(':FN').  However as
  @(tsee defwarrant) is used successfully on @(see scion)s &mdash; functions that
  somehow call @('apply$') &mdash; user-defined symbols can have ilk @(':FN')
  too.</p>

  <p>@('Apply$') has a guard, namely @('(apply$-guard fn args)').  This is an
  exceptionally weak guard, requiring only that @('args') be a true-list and,
  if @('fn') is a cons &mdash; which is automatically treated as a @('LAMBDA')
  object &mdash; the length of @('args') be the length of the second element of
  @('fn').  We discuss <b>guards and guard verification</b> in a subsequent
  section.</p>

  <p><b>Note for Experts</b>: Technically, @('apply$') treats any @('consp')
  object as a @('LAMBDA') object.  But the results are as you'd naively expect
  only if the object is a @(see tame) @('LAMBDA') object.  However, we
  frequently write as though the object must be <i>well-formed</i>, which is
  different from but implies tameness.  What's going on?  The reason for this
  and related discrepancies in the documentation is that there is a tension
  between the logical definition of @('apply$') and the practical business of
  executing it.  The former involves the existence of a model, soundness, and
  the difficulty of proving theorems about @('apply$').  The latter involves
  the Common Lisp compiler.  We want the logical foundations to be simple to
  make it easier to reason about @('apply$'), but the compiler imposes
  unavoidable and complicated restrictions.  The upshot is that the logical
  foundations assign meaning to @('LAMBDA') objects that cannot be compiled.
  Applying merely ``tame'' @('LAMBDA')s is slower than applying ``well-formed''
  ones.  In a sense, by acting like ``tame @('LAMBDA') objects'' and
  ``well-formed @('LAMBDA') objects'' are synonymous we're trying to trick you!
  If you ever have occasion to formally express the restrictions on @('apply$')
  in some theorem, use @('tamep-functionp').  But when you write concrete
  @('LAMBDA') constants, try to keep them well-formed.  We encourage this by
  providing @(tsee lambda$) and by enforcing full blown well-formedness checks
  &mdash; not just tameness checks &mdash; in translate on every quoted @('LAMBDA')
  object entered in a @(':FN') slot.  And we give you ways to circumvent these
  checks &mdash; see @(see gratuitous-lambda-object-restrictions) &mdash; if you really
  mean to supply ill-formed @('LAMBDA') objects to @(':FN') slots.</p>

  <p>Badges are assigned by @(tsee defwarrant), and also by @(tsee defbadge).
  See @(tsee badge) for documentation about how to find out whether a function
  has a badge and how to interpret a badge.  The terms ``out arity'' and
  ``tameness requirements,'' used above, are explained there too.</p>

  <p>Intuitively, the badge of @('fn') tells @('apply$') how each formal of
  @('fn') is used in the definition of @('fn') and there are only three
  ``ilks'' of use.  Ilk @(':FN') means the formal is used exclusively as a
  function, meaning the formal can be passed into @(':FN') slots of other
  functions and eventually reaches @('apply$'), but it is never touched by
  other ACL2 functions.  Ilk @(':EXPR') means the formal is used exclusively as
  an expression, meaning the formal may be passed into @(':EXPR') slots of
  other functions and eventually reaches @(tsee ev$), but is never otherwise
  touched.  Finally, ilk @('NIL') means the formal is treated as an ordinary
  ACL2 object and, in particular, never used as either a function or an
  expression.  The ``tameness requirement'' on each actual is determined by the
  ilk of the corresponding formal: actuals in @(':FN') slots must satisfy
  @('tamep-functionp'), actuals in @(':EXPR') slots must satisfy @('tamep'),
  and there are no requirements on actuals in ilk @('NIL') slots.  For
  discussions of @('tamep-functionp') and @('tamep') see the topic @(see
  tame).</p>

  <p>Generally speaking, if you want to be able to @('apply$') a function you
  should introduce it with @(tsee defun) and then call @(tsee defwarrant) on
  the function name, or use @(tsee defun$), which is a convenient abbreviation
  for the above sequence of events.  But @('defun$') only works for @(':logic')
  mode functions because @('defwarrant') enforces that restriction.  If you
  want to @('apply$') a @(':program') mode function you should define it with
  @('defun') and then call @('defbadge') on its name.</p>

  <p>We summarize the specification of @('apply$') with an example.
  Consider</p>

  @({  (apply$ 'foldr
          '((1 2 3)     ; actual 1
            cons        ; actual 2
            (4 5 6)))   ; actual 3
  })

  <p>The badge of @('foldr'), computed by @('(badge 'foldr)'), is
  @('(APPLY$-BADGE 3 1 NIL :FN NIL)').  The arity is @('3'), the out arity is
  1 (@('foldr') is single-valued) and the ilks list is @('(NIL :FN NIL)').
  Thus the first and third formals have ilk @('NIL') and are treated as
  ordinary objects; the second formal has ilk @(':FN') and is treated as a
  function.  Thus, the tameness requirement is that the second actual to a call
  of @('foldr') must satisfy @('tamep-functionp').  Referring to the
  specification above, we see that the @('apply$') term has the ``naive
  specification'' since @('foldr') has a badge, its out arity is 1, and its
  second actual, @('cons'), satisfies @('tamep-functionp'). That is,</p>

  @({  (apply$ 'foldr
          '((1 2 3)     ; actual 1
            cons        ; actual 2
            (4 5 6)))   ; actual 3
  =
  (foldr '(1 2 3) 'cons '(4 5 6))
  =
  '(1 2 3 4 5 6)})

  <p>The first equation above is just the naive specification of @('apply$')
  and the second equation is just the definition of @('foldr').</p>

  <p>Formals are classified by @(tsee defwarrant) when it tries to compute the
  badge of a function.  What are the rules that lead to a formal being assigned
  ilk @(':FN'), for example?  What does ilk @(':FN') actually signify?</p>

  <p>Let <i>v</i> be the <i>i </i>th formal parameter of a badged function
  <i>fn</i>.  If the badge says that <i>v</i> has ilk @(':FN') then we know
  that <i>v </i> is ``used as a function'' in the definition of <i>fn </i>,
  i.e., the value of <i>v </i> eventually makes its way into the first argument
  of @('apply$').  Furthermore, <i>v </i> is never used any other way: every
  place <i>v </i> occurs in the body it is treated as a function.  And finally,
  in every recursive call of <i>fn </i> <i>v </i> is passed identically in the <i>i
  </i>th argument position of every recursive call.</p>

  <p>If the badge says that formal variable <i>v </i> has ilk @(':EXPR') then
  it signifies analogous conditions except that instead of eventually getting
  into the first argument of @('apply$') it eventually gets into the first
  argument of @('ev$').  We say such formals are ``used as expressions.''
  @(tsee Ev$) is the natural notion of evaluation in this context: look up the
  values of variables in the alist argument to @('ev$'), return quoted
  constants, and otherwise @('apply$') function symbols and @('lambda') objects
  to the recursively obtained list of values returned by evaluating the
  actuals.  However, @('ev$') first checks that the expression is @(tsee
  tamep).</p>

  <p>If the badge says a formal <i>v </i> has ilk @('NIL') in the definition of
  <i>fn </i> then <i>v </i> is <i>never used </i> as a function or as an
  expression in the definition.</p>

  <p>It is the job of @(tsee defwarrant) to analyze a definition and assign
  ilks, if possible.  But it may not be possible!  For example,</p>

  @({(defun foo (x) (apply$ x (list x)))})

  <p>is such a definition.  The formal @('x') is used as a function in its first
  occurrence but is not used as a function in its second.  Thus</p>

  @({(defwarrant foo)})

  <p>will fail.</p>

  <p>When successful, @(tsee defwarrant) also defines the @(tsee warrant)
  function for the function it analyzed.  Warrants are crucial to stating and
  proving theorems about function symbols being applied with @('apply$').  We
  illustrated warrants in the ``Examples'' section above and discuss them
  further in the section on ``Theorems Involving @('Apply$')'' below.  See also
  @(tsee warrant).</p>

  <p>@('Apply$') is a defined function in the ACL2 source code.  We exhibit its
  definition at the end of this documentation but you may also see its
  definition by doing</p>

  @({
  ACL2 !>:pe apply$
  })

  <p>The definition is mutually recursive with</p>

  <ul>
  <li>@(tsee apply$-lambda): used by @('apply$') to handle the case when
  the first argument to @('apply$') is a @('LAMBDA') object.</li>

  <li>@(tsee ev$): used by @('apply$-lambda') to evaluate the body of a
  @('LAMBDA') object in an environment binding the object's formal variables to
  the actuals.</li>

  <li>@(tsee ev$-list): used by @('ev$') to evaluate a list of expressions in
  an environment binding formals to actuals.</li>

  </ul>

  <p>@('Apply$') calls three undefined functions:</p>

  <ul>

  <li>@(tsee apply$-userfn): used by @('apply$') when it is asked to apply
  anything other than a @('LAMBDA') object or a built-in function symbol.  In
  the evaluation theory, we attach a function to @('apply$-userfn') that
  explicitly enforces the tameness requirements for each user-defined
  @(':logic') mode function symbol that has had a badge computed by @(tsee
  defwarrant) and, if those requirements are met, applies the corresponding
  function.  Magically, that attachment to @('apply$-userfn') can also evaluate
  @(':program') mode functions with badges created by @(tsee defbadge).  We say
  ``magically'' because there are no axioms that explain this behavior, just as
  there are no axioms that explain how you can evaluate ordinary calls of
  @(':program') mode functions in the evaluation theory.  But in the proof
  theory @('apply$-userfn') remains undefined.  The value of @('(apply$-userfn
  'fn ...)'), and thus of @('(apply$ 'fn ...)'), is specified by a special
  hypothesis, called the ``warrant for @('fn').''  You can't prove anything
  interesting about the behavior of @('apply$') on a user-defined function
  symbol @('fn') unless the warrant for @('fn') is a governing hypothesis.  We
  discuss warrants in @(tsee warrant).  See also @(tsee defwarrant).</li>

  <li>@('untame-apply$'): used by @('apply$') when it is asked to deal with a
  situation in which tameness is violated.</li>

  <li>@('untame-ev$'): used by @('ev$') when it is asked to deal with a
  situation in which tameness is violated.</li>

  </ul>

  <h3>Definitions Involving on @('Apply$')</h3>

  <p>In one sense, @('apply$') is just an ordinary ACL2 function that takes two
  arguments and returns one result.  Like all ACL2 functions, @('apply$') is
  untyped.  You can supply any two objects as arguments and the axioms tell you
  what the result is &mdash; though sometimes the result is delivered by an
  undefined function.</p>

  <p>But in a deeper sense, if you want @('apply$') to ``behave,'' and in
  particular if you want functions that use @('apply$') to ``behave,'' you have
  to follow certain rules.  For example, ACL2 must be able to determine whether
  a formal parameter is ``used as a function'' in a given definition.
  Basically, you will want every @(':logic') mode function that you define to
  be processed by @('defwarrant') so that it gets a badge and warrant if at all
  possible and at least has a chance of being applied as expected by
  @('apply$').</p>

  <p>The macro @('defun$') is just an abbreviation for a @('defun') followed by
  a @('defwarrant') and it is easy to imagine the other ACL2 definitional
  idioms introduced in the ACL2 Community Books eventually being extended to
  include a subsequent @('defwarrant').</p>

  <p>So the question becomes ``What rules must a @('defun') obey in order to be
  processed successfully by @('defwarrant')?''  The full answer is given in the
  documentation for @(tsee defwarrant).  But here are some guidelines to
  follow:</p>

  <ul>
  <li>use @(':logic') mode,</li>
  <li>use a measure that either returns a natural number or a
      lexicographic combination of natural numbers as defined by the @('llist')
      function in the Community Books at @('books/ordinals/'),</li>
  <li>make sure every function used in the definition has a badge,</li>
  <li>ensure that every @(':FN') slot in the body is occupied either by
      a formal parameter or a quoted, badged function symbol or @(tsee lambda$)
      expression, and</li>
  <li>ensure that no parameter occupying a @(':FN') slot is ever used in a
      slot of any other ilk, and</li>
  <li>ensure that every parameter passed into a @(':FN') slot is passed into
      the same argument position in any recursive calls of the function being
      defined.</li>
  </ul>

  <p>You can certainly violate some of these rules and still get an admissible
  definition.  For example @('(defun rus (x) (not (apply$ x (list x))))') is
  admissible and you can run it on some arguments, e.g., @('(rus 'consp)')
  evaluates to @('T').  You can even prove @('(equal (rus 'consp) t)').  But
  @('(defwarrant rus)') fails because @('rus') violates the rules.  So you will
  not be able to @('apply$') @(''rus').</p>

  <p><b>Note for Experts</b>: One may wonder why it is possible to warrant a
  function, @('fn'), that calls badged but unwarranted functions.  Naively one
  might expect the semantics of @('(apply$ 'fn args') would involve the
  @('ev$') of the body of @('fn') and therefore require the successful
  application (via @('apply$')) of subfunctions in the body.  But that
  expectation is incorrect.  The semantics of @('(apply$ 'fn args)') as
  formalized by the warrant for @('fn') says that (under restrictions on the
  tameness of the arguments) @('(apply$ 'fn args)') is @('(fn (car args) (cadr
  args) ...)').</p>

  <h3>Theorems Involving @('Apply$')</h3>

  <p>Because @('apply$') is undefined on user-defined function symbols and
  warrant hypotheses specify the tameness requirements and value of @('apply$')
  on such symbols, you can't prove much about the application of particular
  user-defined symbols unless you provide the corresponding warrants as
  hypotheses.</p>

  <p>To emphasize this point, suppose @('sq') has been introduced with
  @('defun$') as shown above, then the following top-level evaluation is
  possible:</p>

  @({
  ACL2 !>(apply$ 'sq '(5))
  25
  })

  <p>You might expect to be able to prove the obvious little theorem</p>

  @({(thm (equal (apply$ 'sq '(5)) 25))})

  <p>However, you would be wrong!  While ACL2's evaluation theory assumes all
  warrants, the proof theory does not.  (If it did we could suffer the
  @('LOCAL') problem mentioned in example theorem @('[1]') above and in @(see
  introduction-to-apply$).)  Logically, there is no connection between the
  symbol @(''SQ') and the user-defined function @('sq').  That connection is
  established by warrant.  All the necessary warrants must be explicitly
  provided as hypotheses by the user.</p>

  <p>The warranted version of the little theorem above is easily proved.</p>

  @({(thm (implies (warrant sq) (equal (apply$ 'sq '(5)) 25)))})

  <p>Here @('(warrant sq)') is just an abbreviation for a call of the 0-ary
  function symbol @('apply$-warrant-sq') which is the name of the warrant for
  @('sq').  @('Apply$-warrant-sq') is introduced when @('(defwarrant sq)')
  completes successfully.  In particular, the following is a theorem:</p>

  @({
      (warrant sq)
    <-->
      (force (apply$-warrant-sq))
    <-->
      (((badge 'SQ) = '(APPLY$-BADGE 1 1 . T))
       &
       ((apply$ 'SQ args) = (sq (car args))))
   })

  <p>Note that the @(tsee warrant) macro @(tsee force)s the warrants for the
  functions listed.  But logically @('force') is just the identity.</p>

  <p>Thus, the warrant for @('sq') specifies the value of @('(badge 'sq)') and
  of @('(apply$ 'sq ...)').  Operationally, by forcing the warrant it means the
  absence of a warrant among the hypotheses of a conjecture which is otherwise
  provable just results in a forcing round that highlights the need for the
  warrant.</p>

  <p>If you try to prove the unwarranted version of the little theorem about
  @(''sq') it fails in a forcing round with</p>

  @({
  [1]Goal
  (APPLY$-WARRANT-SQ)
  })

  <p>This is a clear indication that you forgot to provide the warrant.</p>

  <p>You might worry that theorems burdened by warrants are vacuously valid
  because it might be impossible to satisfy all the warrant hypotheses.  You
  needn't worry about this.  <i>There is a model of @('apply$') and all of its
  scions that makes every warrant issued by @('defwarrant') valid.</i> The
  proof of this is sketched in <a
  href='https://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 and fully fleshed out in the comment titled <tt>Essay on
  Admitting a Model for Apply$ and the Functions that Use It</tt> in the ACL2
  source file @('apply-raw.lisp').</p>

  <p>So there are four lessons here:</p>

  <p><b>Lesson 1:</b> When stating theorems involving @('apply$') or scions on
  concrete user-defined functions, provide as additional hypotheses the
  warrants for all user-defined functions that @('apply$') will encounter
  during the proof.  This generally means you should add the hypothesis
  <tt>(warrant </tt><i>fn1 fn2 ... fnk</i><tt>)</tt> typically listing every
  function symbol that appears inside a quoted constant destined for
  @('apply$') or @('ev$') in your conjecture.  In particular, you should
  include every quoted function symbol appearing in a @(':FN') slot of
  @('apply$') or any scion, including every function symbol appearing in the
  body of any @('LAMBDA') object or @('lambda$') term or any @('until'),
  @('when'), or body expressions of @('loop$')s.  (Macro expansion in
  @('lambda$')s and @('loop$')s may introduce function symbols not evident in
  the untranslated forms.  See @(':')@(tsee translam) and @(':')@(tsee
  trans).)</p>

  <p><b>Lesson 2:</b> You need not worry that adding warrant hypotheses makes
  your theorems vacuously valid!  There is a model of @('apply$') and all your
  scions in which all warrants are valid.</p>

  <p><b>Lesson 3:</b> If a proof involving @('apply$') or a scion fails in a
  forcing round with a checkpoint whose conclusion is the warrant for some
  function, you should remember Lesson 1 and include the warrant for that
  function symbol in the hypotheses of your conjecture!  That is, if you forget
  to supply a warrant but your conjecture is otherwise provable, ACL2's
  checkpoints will often remind you.  (It is possible, in the absence of an
  explicit warrant hypothesis, for a proof to fail before the prover detects
  that only the warrant is missing.)</p>

  <p><b>Lesson 4:</b> If a proof involving @('apply$') or a scion fails here
  are some things to think about.  The basic question is whether something is
  ``wrong'' with one or more function symbols supposedly handled by
  @('apply$').  You have to identify which quoted function symbols are not
  being simplified or expanded.  Typically you'll see a checkpoint with a term
  like @('(apply$ 'fn ...)') or @('(ev$ '(fn ...)  ...)') that you expect would
  be expanded into an actual call of @('fn').  In that case, @('fn') is of
  interest.  You should realize that problems of these sorts can drastically
  slow down a proof attempt.  We have seen example proofs where failure to
  simplify an @('apply$') term slowed the proof-attempt down by several orders
  of magnitude.  Here are some questions you should ask yourself about
  @('fn').</p>

  <ul>

  <li>Is @('fn') defined and in @(':logic') mode?  If @('fn') is in
  @(':program') mode it is treated by the prover as an undefined symbol.  You
  should try to convert it @(':logic') mode with @(tsee
  verify-termination).</li>

  <li>Is @('fn') warranted?  If not, see @(tsee defwarrant).  If @('fn') is
  warranted then it is possible @('fn') is not the problem.  Maybe the warrant
  for @('fn') was not provided as a hypothesis?  Normally, missing warrant
  hypotheses are forced, but the proof might have failed for other reasons
  before the warrant for @('fn') was forced.  But you should ask whether
  forcing is disabled; see @(tsee force).</li>

  <li>If you see @('(apply$ 'fn ...)') then perhaps the rewrite rule
  @('APPLY$-fn') is disabled.  That rule is the one that forces the warrant for
  @('fn') and it was proved when @('fn') was warranted.</li>

  <li>Consider how the rewriter handles @('apply$') terms, by reading
  @(see rewriting-calls-of-apply$-ev$-and-loop$-scions) and inspecting
  the enabled/disabled status of the runes mentioned there.</li>

  </ul>

  <p>These issues are discussed further in the documentation for @(tsee
  warrant).</p>

  <p>An unfortunate implication of the need for warrants is highlighted during
  the proofs of measure conjectures while admitting new definitions.
  Consider</p>

  @({
  (defun$ my-cdr (x) (cdr x))

  (defun$ my-len (x)
    (if (endp x)
        0
        (+ 1 (my-len (apply$ 'my-cdr (list x))))))
  })

  <p>The definition of @('my-len') fails!  The reason is that without the
  warrant for @('my-cdr') we cannot prove that the measure decreases in the
  recursion above.  Unfortunately, there is no way to provide a warrant in a
  definition.  At the moment we advise users to avoid the use of @('apply$') &mdash;
  and functions that use @('apply$') &mdash; in ``termination-critical'' roles.  By
  that we mean do not use @('apply$') if its properties are important to proofs
  of your measure conjectures.  This is easy advice to implement in the case of
  @('my-len'), i.e., replace the recursive call above by @('(my-len (my-cdr
  x))').  However, in more sophisticated definitions, e.g., where a @(tsee
  loop$) is being used in recursive calls and the @('loop$') calls user-defined
  functions in its body, following this advice means replacing that @('loop$')s
  by a recursive function.  That is unfortunate since the whole point of
  @('loop$') is to avoid the introduction of such functions!  We hope to
  address this limitation in the future, e.g., by making the definition of
  @('my-len') above be conditional on the warrant for @('my-cdr').</p>

  <h3>Guards and Guard Verification</h3>

  <p>As noted, @('apply$') has a guard of @('(apply$-guard fn args)') and is
  itself guard verified.  The guard is weak, basically requiring that @('fn')
  either be a symbol or a @('LAMBDA') object, that @('args') be a true-list,
  and, when @('fn') is a @('LAMBDA') object, the length of the list of formals
  is equal to the length of @('args').  To verify the guards of a scion you
  must make sure these properties hold of every application of anything in a
  @(':FN') slot.  Mainly you must make sure that every time a function object
  is @('apply$')d, it is applied to a list of the right length.</p>

  <p>Note also that @(see mixed-mode-functions), i.e., @(':logic') mode
  functions that use @(':program') mode functions in slots of @(see ilk)
  @(':FN') or @(':EXPR'), cannot be guard verified.</p>

  <p>But guards arise in another way in connection with @('apply$').  How does
  @('(apply$ fn args)') behave when @('fn') has guards?  The short answer is:
  logically speaking, @('apply$') completely ignores guards.  Guards in ACL2 are
  ``extra-logical.''</p>

  <p>Let's define and warrant a well-guarded version of ``square'',</p>

  @({
  (defun$ squ (n) (declare (xargs :guard (natp n))) (* n n))
  })

  <p>@('Squ') is guard verified.  Now let's consider the little conjecture:</p>

  @({
  (thm (implies (warrant squ) (equal (apply$ 'SQU (list x)) (* x x))))
  })

  <p>Do we need need to require @('(natp x)')?  We would if the logical
  definition of @('apply$') checked the guard of @('fn') before interpreting
  it.  But it does not check.  It just behaves as specified above.  So,
  regardless of whether the guard is satisfied or not, @('(apply$ 'squ (list
  x))') naively expands (under the warrant) to @('(squ x)'), from which the
  rest of the proof follows.</p>

  <p>However, now let's do a top-level evaluation of this @('apply$') term:</p>

  @({
  ACL2 !>(apply$ 'SQU (list 'NAN))

  ACL2 Error in TOP-LEVEL:  The guard for the function call
  (SQU N), which is (NATP N), is violated by the arguments
  in the call (SQU 'NAN).
  })

  <p>(Remember that ACL2's evaluation theory effectively assumes all warrants.)
  What happened?  @('Apply$') expanded to @('(SQU 'NAN)') and that caused the
  usual guard violation, given the default configuration of @(tsee
  set-guard-checking).</p>

  <p>A similar guard violation error is signaled if a guarded @('LAMBDA')
  object is @('apply$')ed to something violating its guard.</p>

  <p>But now consider</p>

  @({
  (defun$ strange (x)
    (declare (xargs :guard t))
    (apply$ 'SQU (list x)))
  })

  <p>This succeeds and @('strange') is now a guard verified, warranted
  function, with a guard of @('T').  This might be surprising since (a) the
  guard of @('strange') tells us nothing about @('x'), (b) @('SQU') is applied
  to @('x'), and (c) we know the guard of @('SQU') requires its argument to be
  a @('natp').  Guard verification ignores the guards of a quoted function
  symbol being applied by a scion.  This may be particularly offensive to one's
  intuitions when the scion is @('apply$') itself, since the appropriate
  information is available.  But consider a call of an arbitrary user-defined
  scion, e.g., @('(my-scion 'SQU x)').  To what arguments will @('my-scion')
  @('apply$') @('SQU')?  And how can the definition of @('my-scion') even
  specify what functional objects are acceptable in its first argument?  This
  is a limitation suffered by ACL2 that a logic with a suitably expressive type
  system would not suffer.  Our way of coping with it is to ignore the guard
  here and make sure that when @('apply$') applies the function symbol executes
  it checks the guard of the symbol.</p>

  <p>Guard verification does not ignore guards of a quoted lambda object being
  @('apply$')ed.  Thus, for example, while @('strange') can be guard
  verified,</p>

  @({
  (defun$ stranger (x)
    (declare (xargs :guard t))
    (apply$ (lambda$ (e) (SQU e)) (list x)))
  })

  <p>cannot be guard verified, because guard verification tries to verify the
  guards of every @('lambda') object in a @(':FN') slot so that the @('lambda')
  object can be marked as guard verified in the compiled @('lambda') cache
  (see @(tsee print-cl-cache)).  But guards of @('lambda') objects must be
  verified independently of the context in which they are used.  To be specific,
  even</p>

  @({
  (defun$ stranger (x)
    (declare (xargs :guard (natp x)))
    (apply$ (lambda$ (e) (SQU e)) (list x)))
  })

  <p>cannot be guard verified because the @('lambda') object's guards are
  verified independently of the context.  The @('lambda') object must carry
  its own guard, as in</p>

  @({
  (defun$ stranger (x)
    (declare (xargs :guard (natp x)))
    (apply$ (lambda$ (e)
              (declare (xargs :guard (natp e)))
              (SQU e))
            (list x)))
  })

  <p>The last definition of stranger can be guard verified, the @('lambda')
  object is so marked in the cache and compiled, and if that @('lambda') object
  is used in any other context it is recognized as being guard verified.  The
  guard for that @('lambda') is checked when the object is @('apply$')ed but if
  the check approves then the body of the @('lambda') is executed as compiled
  code without further guard checking.</p>

  <p>While @('apply$') is not evident in a @(tsee loop$) statement like</p>

  @({
  (loop$ for e in lst collect (SQU e))
  })

  <p>similar treatment is given.  In particular, the @('loop$') above cannot
  be guard verified but</p>

  @({
  (loop$ for e in lst collect :guard (natp e) (SQU e))
  })

  <p>can be and is compiled into a Common Lisp @('loop').  Recall also from
  the @(tsee loop$) documentation that the formal semantics of the above
  statement is essentially</p>

  @({
  (collect$ (lambda$ (e)
              (declare (xargs :guard (natp e)))
              (SQU e))
            lst)
  })

  <p>so guard verification of the @('loop$') also compiles and marks that
  @('lambda') expression as guard verified.</p>

  <p>So now let's return to consideration of</p>

  @({
  (defun$ strange (x)
    (declare (xargs :guard t))
    (apply$ 'SQU (list x)))
  })

  <p>which we've seen is guard verified despite the fact that @('SQU') expects
  a natural number and will not necessarily be given one.  What happens when we
  call @('strange') on a non-natural?</p>

  @({
  ACL2 !>(strange 'NAN)

  ACL2 Error in TOP-LEVEL:  The guard for the function call (SQU N),
  which is (NATP N), is violated by the arguments in the call (SQU 'NAN).

  ACL2 !>:q

  Exiting the ACL2 read-eval-print loop.  To re-enter, execute (LP).
  ? (strange 'nan)

  ACL2 Error in ACL2-INTERFACE:  The guard for the function call (SQU N),
  which is (NATP N), is violated by the arguments in the call (SQU 'NAN).
  })

  <p>We see that we can provoke a guard violation with @('strange')
  even though it is guard verified with a guard of @('T').  Furthermore,
  we get the error both in the ACL2 read-eval-print loop and in the raw
  Lisp under ACL2.  (Be careful though about exiting the ACL2 loop; see @(see
  q).)</p>

  <p>This might at first violate your understanding of the link between ACL2
  and Common Lisp.  Naively, a guard verified ACL2 function with a guard of
  @('T') never causes a runtime error in Common Lisp.  But that's not quite
  what the guarantee is.  Such a function will never cause a hard Lisp error,
  other than possibly resource errors like running out of memory or stack
  space.  Neither of the errors above were signaled by Common Lisp.  They were
  ``soft'' ACL2 errors.  In particular, when @('apply$') calls @('squ') above,
  even when running in raw Lisp, it actually calls the executable counterpart
  of @('squ'), which checks guards at runtime and executes properly under the
  ACL2 axioms.</p>

  @({
  ACL2 !>(set-guard-checking :none)

  Turning off guard checking entirely.

  ACL2 >(strange 'nan)
  0
  })

  <p>The last evaluation can be explained by the fact that ACL2 multiplication
  defaults non-numbers to 0.</p>

  <p>We discuss the evaluation of ground @('apply$') terms in the evaluation
  theory further below.</p>

  <p>When the guard conjectures of a function are proved all necessary warrants
  are assumed.  This is unlike what happens when the measure conjectures are
  proved.  The reason we can assume warrants during guard verification is that
  guard verification is relevant in the evaluation theory, where attachments
  are allowed and all warrants have true attachments.</p>

  <h3>Top-Level Evaluation of Apply$</h3>

  <p>As noted, ACL2's evaluation theory implicitly assumes all warrants
  produced by @(tsee defwarrant).  See @(see
  guarantees-of-the-top-level-loop). Since top-level evaluation in ACL2 is
  conducted in the evaluation theory, ground calls of @('apply$') &mdash;
  whether literally in top-level input to the ACL2 read-eval-print loop or
  hidden inside scions called from the top-level &mdash; can be evaluated on
  quoted warranted function symbols and @(tsee lambda$) expressions &mdash;
  provided the @(see tame)ness restrictions are met.  This is in contrast to
  opportunities for evaluation of ground @('apply$') expressions arising in
  proofs, where warrant hypotheses must be explicit.</p>

  <p>In this section we focus on calls of @('apply$') arising in the evaluation
  theory.  We start with a discussion of the use of @('apply$') with warranted
  @(':logic') mode functions.  We then describe how @('apply$') handles badged
  @(':program') mode functions.  Note that a mere badge is <i>not</i>
  sufficient for evaluation when using @('apply$') on a @(':logic') mode
  function that is not warranted; see @(tsee defbadge) and @(see
  guarantees-of-the-top-level-loop) for discussion of this case.  In short:
  evaluation involving @(':logic') mode functions is expected to respect the
  evaluation theory, and while @('defwarrant') extends the evaluation theory
  appropriately, @('defbadge') does not.</p>

  <p>Evaluation of @('apply$') terms in the evaluation theory respects guards
  on quoted function symbols and @(tsee lambda$) expressions (which is to say,
  on the quoted well-formed @('LAMBDA') objects that @(tsee lambda$) produces).
  So consider a call of @('apply$') on @('fn') and @('args') in the evaluation
  theory, where @('fn') is a warranted function symbol or a well-formed (and
  thus tame) @('LAMBDA') object.  Here's what happens.  Except where noted, the
  description below applies both to warranted @(':logic') and badged
  @(':program') mode functions.</p>

  <p>@('Apply$') determines whether @('fn')'s tameness restrictions are met by
  @('args').  Tameness is a syntactic property and so can be checked.  If the
  function's tameness restrictions are not met, an error is caused.</p>

  <p>If the tameness restrictions are met, @('apply$') determines whether
  @('fn') has been guard verified.  In the case of function symbols this is a
  simple lookup on the property list of @('fn').  (Of course, this check fails
  for @(':program') mode functions.)  In the case of @('LAMBDA') objects it is
  a cache query (see @(tsee print-cl-cache)) and if the query reveals that we
  have not yet tried to verify the guards of this @('LAMBDA') object,
  @('apply$') uses tau reasoning alone (see @(see
  introduction-to-the-tau-system)) to try to verify the guard conjectures.</p>

  <p><b>Note:</b>An important distinction between the runtime handling of
  function symbols versus @('LAMBDA') objects by @('apply$') is that function
  symbols can only be guard verified by prior events, e.g., the introductory
  @(tsee defun) or a subsequent @('verify-guards'), but @('apply$') tries to
  verify the guards of @('LAMBDA') objects <i>on the fly</i>!  The reason for
  this distinction is that we anticipate that many @('LAMBDA') objects will not
  be associated with any event.  For example, an ACL2 macro might generate a
  call of a scion on a never-before-seen @('LAMBDA') object and that
  @('LAMBDA') object may only be seen by the top-level evaluator.  We discuss
  this further in @(tsee verify-guards)</p>

  <p>If @('fn') is guard verified, @('apply$') next checks whether @('fn')'s
  guard holds of the actuals in @('args').  This is done by evaluation of the
  compiled code for the guard on @('args').</p>

  <p>If the guard check of @('args') succeeds, a compiled version of @('fn') is
  applied to @('args').  If the check fails, a guard violation is signaled or
  else the application of @('fn') to @('args') is interpreted under the
  definitional axioms of @('apply$') and @('ev$'), depending on how @(tsee
  set-guard-checking) has been configured.</p>

  <p>Finally, if @('fn') is not guard verified, the application of @('fn') to @('args')
  is interpreted under the definitional axioms of @('apply$') and @('ev$').</p>

  <p>We discuss the cache that supports @('LAMBDA') application in @(tsee
  print-cl-cache).  See also the discussion of guard verification in @(tsee
  lambda$).  It should be noted that a @('LAMBDA') object can also be guard
  verified using the @(tsee verify-guards) event.  This brings the full power
  of the prover to bear on the guard verification of the @('LAMBDA') object,
  instead of relying just on the tau system.</p>

  <p>Users are accustomed to executing @(':program') mode functions at the
  top-level of the ACL2 read-eval-print loop.  Indeed, the prover itself and
  the various event commands are mostly written in @(':program') mode.
  Furthermore, the evaluation theory is described as an extension of the proof
  theory, i.e., as an axiomatic theory.  And yet no part of that axiomatization
  explains how @(':program') mode functions are run!  It simply isn't
  important.  The implementation supports it and no questions are asked.  We,
  the implementors of ACL2, view top-level evaluation of @(':program') mode
  functions as a convenience not affecting the consistency of the proof theory.
  No inconsistency results from starting a non-terminating computation because
  you can never inspect the result, whereas if you added the corresponding
  definition as an axiom you might be able to prove something contradictory.
  So we regard the seamless execution of @(':program') mode functions as a
  convenience to the user who might use them to inspect the ACL2 logical world,
  gather data, experiment with constrained formal models by attaching
  executable code to unspecified functions, prototype something to be
  formalized, etc.  In that spirit, we have arranged for @('apply$') to handle
  @(':program') mode functions <i>provided they have badges</i>.  Badges are
  critical because it means that execution of the functions won't ``go outside
  the sandbox.''  However, @('apply$') runs @(':program') mode functions in
  @(tsee safe-mode) to ensure the functional substitutivity of @('apply$'):
  identical calls must always yield identical results.</p>

  <p>It may seem counterintuitive that a top-level @('apply$') of a @(':logic')
  mode function cannot be executed unless @('defwarrant') has succeeded but a
  top-level @('apply$') of a @(':program') mode function can be executed.  As
  noted earlier, the reason is simple: execution of @(':logic') mode functions
  is justified by the axioms of the evaluation theory while no such assurances
  are offered for @(':program') mode functions.</p>

  <h3>Logical Definitions</h3>

  <p>In the following definitions, @('apply$-userfn') is an undefined function
  that is constrained by warrants to describe the tameness requirement and
  behavior of @('apply$') on specific function symbols.  The functions
  @('untame-apply$') and @('untame-ev$') are simply undefined functions for
  giving unspecified values when untame objects are being used.</p>

  @(def apply$)

  @(def apply$-lambda)

  @(def apply$-lambda-logical)

  @(def ev$)

  @(def ev$-list)

  @(def apply$-guard)

  @(def apply$-lambda-guard)

  ")
other
(defxdoc apply$-guard
  :parents (apply$)
  :short "The guard on @('apply$')"
  :long "<p>The guard on @('(apply$ fn lst)') is @('(apply$-guard fn lst)') which
  is extraordinarily weak.</p>

  @(def apply$-guard)

  <p>where</p>

  @(def apply$-lambda-guard)

  <p>This guard is just strong enough to allow the definitions of the functions
  in the @('apply$') clique to be guard verified.  It does not guarantee that
  @('fn') is tame or well-formed or that @('args') satisfy the guard of
  @('fn').  The last condition is in fact impossible to state given the untyped
  nature of ACL2.  Thus, @('(apply$ fn args)') has to check tameness,
  well-formedness, guard verified, and that @('fn')'s guard is satisfied by
  @('args') when the @('apply$') is executed in the evaluation theory.</p>

  <p>The issue of guards and guard verification of definitions involving
  @('apply$') is further discussed in @(tsee apply$) and in @(tsee
  verify-guards).</p>")
other
(defxdoc apply$-lambda
  :parents (apply$)
  :short "Used by @('apply$') on @('LAMBDA') objects"
  :long "<p>When @('apply$') is given a @('consp') object as its first argument
  it treats it as a @('LAMBDA') expression and calls this function to apply it.
  This function evaluates the body of the object with @('ev$') under an alist
  binding the formals of the object to the actuals.  See @(tsee apply$) for
  details.</p>")
other
(defxdoc apply$-lambda-guard
  :parents (apply$)
  :short "The guard on @('apply$-lambda')"
  :long "<p>The guard on @('(apply$-lambda fn lst)') is @('(apply$-lambda-guard
  fn lst)') which is extraordinarily weak.</p>

  @(def apply$-lambda-guard)

  <p>This guard is just strong enough to allow the definitions of the functions
  in the @('apply$') clique to be guard verified.  It does not guarantee that
  @('fn') is @('tame') or well-formed or that @('args') satisfy the guard of
  @('fn').  The last condition is in fact impossible to state given the untyped
  nature of ACL2.  Thus, @('(apply$ fn args)') has to check tameness,
  well-formedness, guard verified and that @('fn')'s guard is satisfied by
  @('args') when the @('apply$') is executed in the evaluation theory.</p>

  <p>The issue of guards and guard verification of definitions involving
  @('apply$') is further discussed in @(tsee apply$) and in @(tsee
  verify-guards).</p>")
other
(defxdoc apply$-userfn
  :parents (apply$)
  :short "Undefined function used by @('apply$') on non-primitives"
  :long "<p>When @('apply$') is given a non-primitive function symbol it calls
   this function to determine the results of applying that symbol to the given
   arguments.  But this function is undefined.  In the proof theory, its value
   on a given function symbol @('fn') is specified, if at all, by the @(tsee
   warrant) for @('fn') which must be available as a hypothesis in the formula
   being proved.  In the evaluation theory, @('apply$-userfn') has an
   attachment that makes it behave as though all warrants are assumed.  See
   @(tsee apply$) for details.</p>")
other
(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 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>")
other
(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)")
other
(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)")
other
(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 some information about it including the formal
 parameters, the @(see guard) expression, the output @(see signature), the
 deduced type, the @(see constraint) (if any), and its @(tsee badge) and @(tsee
 warrant), if any.</p>")
other
(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)")
other
(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).")
other
(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)")
other
(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)")
other
(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>

 <h3>The Logical Description of ACL2 Arrays</h3>

 <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) essentially 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>

 <h3>The Implementation of ACL2 Arrays</h3>

 <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 writes into a
 Common Lisp array all of the index/value pairs of @('a''), initializing
 unassigned indices with the default value.  In general this is a new array,
 which becomes the raw lisp array of @('name').  However, if a raw lisp array
 is already associated with @('name') and is at least as long as the dimension
 specified in the @(see header), then that array is reused and all indices out
 of range are ignored.  (Such reuse can be avoided; see @(see flush-compress)
 for how to remove the existing association of a raw lisp array with a name.)
 Either way, @(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>

 <h3>Some Programming Examples</h3>

 <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>")
other
(defxdoc arrays-example
  :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 !>
 })")
other
(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>

 <p>Note that @(tsee aset1) is marked as having @(tsee invariant-risk), which
 can affect the execution of @(':')@(tsee program)-mode functions.  To get
 around this problem (but only with great care!), see @(see aset1-trusted).</p>

 @(def aset1)")
other
(defxdoc aset1-trusted
  :parents (arrays acl2-built-ins aset1)
  :short "Set the elements of a 1-dimensional array without @(see
 invariant-risk)"
  :long "@({
 Example Form:
 (aset1-trusted 'delta1 a (+ i k) 27)

 General Form:
 (aset1-trusted name alist index val)
 })

 <p>This utility is identical to @(tsee aset1); in fact, it has the same guard.
 The difference is that it does not carry @(see invariant-risk).  Because of
 that, functions that call @('aset1-trusted') may suffer from invariant-risk
 but not be noted by the system as carrying invariant-risk.  Therefore,
 @('aset1-trusted') it is @(see untouchable) and should be used with great
 care.  If your system consists of @(':')@(tsee logic)-mode functions, then
 there is no reason to use @('aset1-trusted'), because only @(':')@(tsee
 program)-mode functions truly carry invariant-risk.</p>

 @(def aset1-trusted)")
other
(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)")
other
(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)")
other
(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>See also @(tsee assert*).  Both @(tsee assert$) and @(tsee 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>

 <p>Also see @(see assert-event) for an assertion-checking utility that is an
 @(see event).</p>")
other
(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>

 <p>Also see @(see assert-event) for an assertion-checking utility that is an
 @(see event).</p>

 @(def assert*)")
other
(defxdoc assert-event
  :parents (events errors)
  :short "Assert that a given form returns a non-@('nil') value"
  :long "<p>@('Assert-event') provides a flexible way to check that evaluation
 of an expression returns a non-@('nil') value, causing an error otherwise.
 Calls of @('assert-event') are @(see event) forms; thus, they may occur in
 @(see books) as well as @(tsee encapsulate) and @(tsee progn) events.  See
 also @(see assert!) and @(see assert!-stobj) for simple interfaces to
 @('assert-event').  See @(see assert$) and @(see assert*) for
 assertion-checking utilities to use in programs.</p>

 <p>Basic calls of @('assert-event') will take just one argument, called an
 ``assertion'', which is a form that evaluates to a single value that is not a
 @(see stobj).  The following log shows a successful invocation &mdash; one
 where the assertion evaluates to a non-@('nil') value.</p>

 @({
 ACL2 !>(assert-event (equal (+ 3 4) 7))
  :PASSED
 ACL2 !>
 })

 <p>Such a use of @('assert-event') will probably suffice for most users, that
 is, where the form evaluates to a single non-stobj value and there are no
 keyword arguments.  The keyword arguments, which are optional and discussed
 below, extend that functionality, for example: multiple values are permitted
 by keyword @(':stobjs-out'), and keyword @(':on-skip-proofs') can override the
 default behavior of ignoring assertions when proofs are being skipped.</p>

 @({
 General Form:
 (assert-event assertion
               :event event           ; default nil
               ;; evaluated keyword arguments:
               :ctx                   ; default 'assert-event
               :msg msg               ; default t
               :on-skip-proofs sp     ; default nil
               :safe-mode safe-mode   ; default :same
               :stobjs-out stobjs-out ; default nil
               )
 })

 <p>where @('assertion') and @('event') are not evaluated but all the other
 arguments are evaluated, with the defaults shown above corresponding to values
 after evaluation.</p>

 <p>The following example illustrates all of the keyword arguments, which are
 documented below.</p>

 @({
 (assert-event (mv (equal (+ 3 4) 7) state)
               :event (defun f (x) (cons x x))
               :ctx '(assert-event . <some-mv>)
               :msg (msg "Oops, I forgot what ~x0+~x1 is!" 3 4)
               :on-skip-proofs t
               :safe-mode nil
               :stobjs-out '(nil state))
 })

 <p>@('Assert-event') is a macro whose expansion directly produces a call of
 the primitive event, @('value-triple'), where: if a call of @('assert-event')
 specifies @(':msg msg'), then the corresponding call of @('value-triple')
 specifies @(':check (or msg t)').  But unlike @('value-triple'),
 @('assert-event') can specify an event to evaluate when the assertion has
 non-@('nil') value, using the @(':event') keyword.  (You can get a sense of
 the @('value-triple') call generated from an @('assert-event') call by using
 @(':')@(tsee trans1) on the @('assert-event') form.)  The remaining keyword
 arguments of @('assert-event') are also arguments of @('value-triple').  Here
 is a brief summary of the keyword arguments, but <b>NOTE</b>: see @(see
 value-triple) for more detailed explanations of keywords other than
 @(':EVENT').</p>

 <p>@(':EVENT event') (default @('nil')): When @('event') is not @('nil'), it
 should be an @(see event), that is, a form that may be in a book or a call of
 @(tsee encapsulate) or @(tsee progn).  If the assertion evaluates to a
 non-@('nil') value (or to multiple values where the first value is not a stobj
 and is non-@('nil'); see @(':STOBJS-OUT') below), then @('event') is
 evaluated; otherwise the evaluation results in an error.</p>

 <p>@(':CTX ctx') (default: @(''assert-event')): context for error messages.</p>

 <p>@(':MSG msg') (default: @('t')): message to print when there is an
 error (equivalent to keyword argument @(':CHECK') of @(tsee
 value-triple)).</p>

 <p>@(':ON-SKIP-PROOFS sp') (default: @('nil')): supply @('t') to evaluate the
 assertion even when skipping proofs (i.e., during @(tsee include-book) or the
 second pass of an @(tsee encapsulate) event, or after invoking @(tsee
 set-ld-skip-proofsp) to skip proofs).</p>

 <p>@(':SAFE-MODE safe-mode') (default: @(':same')): provides backward
 compatibility, but is probably best ignored.</p>

 <p>@(':STOBJS-OUT stobjs-out') (default: @('nil')): specify @(':auto') to
 allow any return, even with multiple values provided the first return value is
 not a @(see stobj); or specify a list starting with @('nil'), corresponding to
 the multiple values returned, with stobjs in stobj positions and @('nil')
 elsewhere.  A @('stobjs-out') of @('nil') is treated as @('(nil)').  The first
 return value is the one checked to be non-@('nil') with one exception: when an
 @(see error-triple) @('(mv erp val state)') is returned, @('erp') must be
 @('nil') and it is @('val') that is checked to be non-@('nil').</p>")
other
(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>")
other
(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)")
other
(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)")
other
(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)")
other
(defxdoc assume-true-false-aggressive-p
  :parents (rewrite system-attachments)
  :short "Control rewriter's use of the @(see type-alist) with @('IF') calls"
  :long "<p>This topic concerns an advanced control for the ACL2 prover.</p>

 <p>This zero-ary attachable system function controls the rewriter's use of the
 @(see type-alist) when diving into calls of @('IF').  By default, when ACL2
 rewrites what amounts to @('(if (or test1 test2) (if test1 _ x) _)'), the
 type-alist will fail to note that @('test2') is true when rewriting @('x').
 Attach the function @('constant-t-function-arity-0') to strengthen the use of
 the type-alist so that @('test2') is instead noted as true in that case.  Note
 that this strengthening may slow down ACL2 considerably in some cases, and
 should rarely if ever be necessary when calling the prover; but it can be
 useful in applications that call the rewriter directly.  Attach the function
 @('constant-nil-function-arity-0') to restore the default behavior.</p>")
other
(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)")
other
(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>

 @(def atom-listp)")
other
(defxdoc attach-stobj
  :parents (defabsstobj)
  :short "Attach an &ldquo;implementation @(see stobj)&rdquo; to an attachable
 stobj"
  :long "<p>For an illustration of @('attach-stobj'), see @(see
 community-books) directory @('books/demos/attach-stobj/'), in particular file
 @('README.txt') in that directory.  An overview of the subject of this topic
 may be found in the paper, <a
 href='https://cgi.cse.unsw.edu.au/~eptcs/paper.cgi?ACL2in2025.7'>&ldquo;Extended
 Abstract: Mutable Objects with Several Implementations&rdquo;</a> by Matt
 Kaufmann, Yahya Sohail, and Warren A. Hunt Jr.</p>

 <p>This topic assumes familiarity with abstract @(see stobj)s; see @(see
 defabsstobj).  It documents a way to modify the foundation and primitives of
 an abstract @(see stobj), @('gen'), that is introduced by @('defabsstobj')
 using the keyword argument @(':attachable t').  Such a stobj is called an
 <i>attachable</i> stobj.  Execution of its primitives can be provided by
 corresponding primitives of a specified abstract stobj, @('impl'), which we
 say is <i>attached to</i> @('gen') (or: @('impl') is the <i>implementation
 stobj attached to</i> @('gen')); said differently, @('gen') has @('impl') as
 an attachment.  That relationship is specified by the following</p>

 @({
 General Form:
 (attach-stobj gen impl)
 })

 <p>where @('gen') and @('impl') are symbols, @('gen') is not currently the
 @(see name) of any @(see event) (function, macro, constant, stobj, etc.), and
 @('impl') is an abstract stobj.  A subsequent attempt to introduce @('gen') as
 an attachable stobj will require @('gen') and @('impl') to have
 <i>corresponding logical skeletons</i> as described below.  In that case, the
 foundation of @('gen'), as well as execution of the primitives of @('gen'),
 will effectively be provided by @('impl'); details are below.</p>

 <p>In the General Form above, @('impl') is allowed to be @('nil'), i.e., the
 event @('(attach-stobj gen nil)') is legal, where it is still required that
 @('gen') not be the name of any existing event.  The effect of this
 ``attachment'' of @('nil') is to cancel the effect of any previous
 @('(attach-stobj gen impl)') on any future introduction of @('gen').  Below,
 we assume the common case that @('impl') is not @('nil').</p>

 <p>Note that @('impl') may itself have an attachment, say, @('impl2'), in
 which case we say that @('impl2') is attached to @('gen').  If furthermore
 @('impl3') is attached to @('impl2'), then @('impl3') is said to be attached
 to @('gen'); and so on.</p>

 <p>The guiding principle is that @('gen') is modified by its attachment to
 @('impl') so that @('gen') behaves exactly as @('impl') except for the names
 introduced and the @(':non-executable') keyword.  Specifically, if @('impl')
 is attached to @('gen'), then the following properties hold.  (See @(see
 defabsstobj) for the notion of a &ldquo;function spec&rdquo; and its
 &ldquo;completion&rdquo;.)</p>

 <ul>

 <li>Both @('gen') and @('impl') are abstract stobjs, and moreover, @('gen') is
 an attachable stobj.</li>

 <li>@('Impl') was introduced before the use of @('attach-stobj') to attach
 @('impl') to @('gen'), which took place before @('gen') was introduced.</li>

 <li>@('Gen') and @('impl') have corresponding logical skeletons (as defined
 below).  In particular, each primitive of @('gen') has the same logical
 meaning (i.e., the same @(':logic') function) as the corresponding primitive
 of @('impl').</li>

 <li>For each primitive @('p_gen') of @('gen') and corresponding primitive
 @('p_impl') of @('impl'), if @('(p_impl . kwd-alist)') is the completion of
 the corresponding function spec for @('p_impl'), then the function spec for
 @('p_gen') is effectively given as @('(p_gen . kwd-alist)'), with the
 following exception.  Each @(':updater') keyword is replaced appropriately, as
 follows: if @('kwd-alist') specifies @(':updater u_impl') and primitive
 @('u_gen') of @('gen') corresponds to primitive @('u_impl') of @('impl'), then
 @(':updater u_impl') is replaced by @(':updater u_gen') to obtain the
 effective function spec for @('p_gen').</li>

 <li>The @(':protect-default') and @(':congruent-to') keyword arguments for
 @('gen') are effectively those of @('impl').</li>

 <li>The @(':non-executable') keyword argument for @('gen') is unchanged by the
 attachment.</li>

 </ul>

 <p>As promised above, we now define when two @('defabsstobj') events have
 <i>corresponding logical skeletons</i>, as follows.  The @(':exports') keyword
 argument of each must be of the same length, establishing a positional one-one
 correspondence between them.  Corresponding exports (i.e., exports in the same
 position) must have the same @(':logic') functions and, if one of them
 specifies @(':updater u1'), then the other must specify @(':updater u2') where
 @('u1') and @('u2') correspond.</p>

 <p>Remarks on Performance.  Stobj attachments are designed to be efficient.
 There is no indirection: in raw Lisp, each primitive macroexpands to a call of
 the @(':exec') primitive of the attachment (which is itself a macro call).
 The trade-off is that when a function @('F') is defined in the course of
 evaluating an @(tsee include-book) event, then if the guard or body of @('F')
 calls an attachable stobj primitive &mdash; either directly or by way of
 inline functions or macroexpansion, and whether or not that stobj has an
 attachment &mdash; then @('F') will be compiled at that time.  (This is in
 contrast to the usual case, where compiled code from the book's compiled file
 will be installed to avoid such recompilation.)  Most likely this will not be
 a noticeable problem in practice, but if it is, then one can define a wrapper
 &mdash; a function that does nothing more than call the primitive &mdash; to
 avoid such recompilation at the cost of a runtime function call for each such
 primitive.  End of Remarks on Performance.</p>

 <p>Note that the notion of redundancy for @('defabsstobj') was not changed by
 support for the @(':attachable') keyword.  As noted in the topic @(see
 redundant-events), a @('defabsstobj') event is redundant if there is already
 an identical such event in the logical @(see world).</p>

 <p>The @(see community-books) directory @('system/tests/attachable-stobjs/')
 has examples that use attachable stobjs.</p>")
other
(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>")
other
(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>")
other
(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 <a href='https://www.cs.utexas.edu/users/moore/acl2/'>ACL2 Home Page</a>
 on the web contains links to demos, publications, mailing lists, installation
 instructions, and more &mdash; and, especially, to the
 @(`(:raw (combined-manual-ref))`), which provides online documentation for
 ACL2 and its libraries, known as ``books''.</p>

 <p>For example, to use the online documentation 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><see topic='@(url |What Is ACL2(Q)|)'><img
 src='res/tours/flying.gif'></img></see></p>")
other
(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>")
other
(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 displays 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>")
other
(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>")
other
(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>

 <ul>

 <li>how to use the ACL2 documentation,</li>

 <li>what happens when the above definition is submitted to ACL2,</li>

 <li>what happens when you evaluate calls of @('app'),</li>

 <li>what one simple theorem about @('app') looks like,</li>

 <li>how ACL2 proves the theorem, and</li>

 <li>how that theorem can be used in another proof.</li>

 </ul>

 <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>")
other
(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>")
other
(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>")
other
(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 ``type reasoning'', which uses rules of class @(tsee
 type-prescription) rules (see @(see type-reasoning)).  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, type 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
 })")
other
(defxdoc backquote
  :parents (reader)
  :short "Variant of quotation introducing templates for data structures"
  :long "<p>ACL2 supports the backquote (@('`')) construct of Common Lisp.  See
 any Common Lisp documentation for details, for example, its <a
 href='https://www.lispworks.com/documentation/HyperSpec/Body/02_df.htm'>discussion
 in the Common Lisp HyperSpec</a>.  Here we give only a brief introduction.</p>

 <p>Together with the use of comma (@(',')) and comma-atsign (@(',@')),
 backquote provides a variant of quote that supports an escape mechanism, as
 illustrated by the following examples.</p>

 @({
 ACL2 !>`(a b c)
 (A B C)
 ACL2 !>(let ((x '(a b c))) `(1 ,(cdr x) 2))
 (1 (B C) 2)
 ACL2 !>(let ((x '(a b c))) `(1 ,@(cdr x) 2))
 (1 B C 2)
 ACL2 !>
 })

 <p>The first example above illustrates that backquote is much like quote.  The
 second example shows how a comma escapes from the quotation, inserting the
 value of the object that follows the comma.  The third example is similar to
 the second, except that it uses comma followed by an atsign, which splices in
 the value (which must satisfy @(tsee true-listp)) rather than inserting
 it.</p>")
other
(defxdoc badge
  :parents (apply$)
  :short "Syntactic requirements on a function symbol to be used by @('apply$')"
  :long "<p>``Badge'' is both the name of an ACL2 function and the name of a
  concept key to the @(tsee apply$) machinery.  We discuss the function named
  @('badge') first.  The discussion also mentions the concept of warrants,
  which are easily confused with badges.  See the discussion of <b>Badges
  versus Warrants</b> at the top of @('defbadge').  But roughly put, badges
  extend the ACL2 syntax and warrants extend the proof theory.  You'll need a
  badge for @('fn') to allow the system to syntactically analyze @('(apply$ 'fn
  ...)').  You'll need a both a badge and a warrant for @('fn') if you wish to
  reason about that term with ACL2.</p>

  <p>General Form:</p>
  @({(badge fn)})

  <p>The argument, @('fn'), is expected to be a function symbol.  If @('fn') is
  one of about 800 ACL2 primitives (discussed below) or is a user-defined
  function successfully processed by either the event @(tsee defbadge) or the
  event @(tsee defwarrant), the result is an object, called the ``badge'' of
  @('fn'), which among other things specifies the @(see ilk) of each formal of
  @('fn').  Otherwise, an error is caused.  We explain below, where we define
  the concepts of the ``out arity,'' ``ilks,'' and ``tameness requirements'' of
  @('fn')'s badge.</p>

  <p>A function symbol must have a badge in order to @('apply$') the symbol and
  it is up to you, the user, to invoke an event that will assign a badge to
  your user-defined functions, if possible.  @('Defbadge') will assign a badge
  to a function symbol, if possible, and @('defwarrant') will assign both a
  badge (if the function symbol doesn't already have one) and a @(tsee
  warrant), if possible.  The macro @(tsee defun$) is just an abbreviation for
  a @('defun') followed by a @('defwarrant').  Almost all primitive system
  functions already have badges.</p>

  <p>The complete list of badged primitives can be seen by evaluating</p>

  @({
  (append '(BADGE TAMEP TAMEP-FUNCTIONP SUITABLY-TAMEP-LISTP
                  APPLY$ EV$)
          (strip-cars *badge-prim-falist*))
  })

  <p>@('Badge') is a defined function in ACL2.  You can inspect its definition
  with</p>

  @({ACL2 !>:pe badge
  })

  <p>and see that after handling the built-in symbols it defers to the
  undefined function @(tsee badge-userfn).  In the evaluation theory,
  @('badge-userfn') has an attachment that returns the badge computed by
  @('defbadge') or @('defwarrant').  But in the proof theory, @('badge-userfn')
  is undefined and the @(tsee warrant) for @('fn') specifies the badge of
  @('fn').  Thus, in the proof theory, you cannot reason about the application
  of a non-primitive function unless there is a warrant for the function
  available as a hypothesis.</p>

  <p>The rest of this documentation illustrates and explains what badges mean,
  starting with a few examples.</p>

  @({
  ACL2 !>(badge 'cons)
  (APPLY$-BADGE 2 1 . T)

  ACL2 !>(badge 'apply$)
  (APPLY$-BADGE 2 1 :FN NIL)

  ACL2 !>(badge 'foldr)
  (APPLY$-BADGE 3 1 NIL :FN NIL)
  })

  <p>The last example assumes that @('foldr') has been defined with</p>

  @({
  (defun$ foldr (lst fn init)
    (if (endp lst)
        init
        (apply$ fn
                (list (car lst)
                      (foldr (cdr lst) fn init)))))
  })

  <p>In general, badges have the form @('(APPLY$-BADGE n k . ilks)'), where
  @('n') is the arity of @('fn'), @('k') is the out arity (i.e., the number of
  results returned by @('fn')) and @('ilks') is either @('T') or a list of
  @('n') tokens.  Each token is either @(':FN'), @(':EXPR'), or @('NIL').</p>

  <p>The badge of @('fn'), if any, is computed when the event @('(defbadge
  fn)') or @('(defwarrant fn)') completes successfully.  See @(tsee defbadge)
  for a sketch of the algorithm used to compute badges.  Here though we are
  just concerned with how badges impact @('apply$').</p>

  <p>The @('ilks') of a function, @('fn'), determines the ``tameness
  requirements'' mentioned in the specification of @(tsee apply$).  When the
  @('ilks') component of @('fn')'s badge is a list, it has as many elements as
  there are formals to @('fn') and each successive element is called the
  <i>ilk</i> of the corresponding formal.  For example, given the definition of
  @('foldr') above and the badge shown for it, the first and third formals,
  @('lst') and @('init'), each have ilk @('NIL') and the second formal,
  @('fn'), has ilk @(':FN').  In the special case that @('ilks') is not a list
  it is @('T') and we just say each formal has <i>ilk</i> @('NIL') -- treating
  that @('T') as a suitably long list of @('NIL')s.</p>

  <p>Each non-@('NIL') ilk imposes a <i>tameness requirement</i> on @('(apply$
  fn args)').  If a formal has ilk @(':FN') the corresponding element of
  @('args') must satisfy @('tamep-functionp').  If a formal has ilk @(':EXPR')
  the corresponding element of @('args') must satisfy @('tamep').  Ilk @('NIL')
  imposes no requirement.  (Thus, if the @('ilks') of @('fn')'s badge is
  @('T'), as it is for @('cons') for example, there is no tameness requirement
  at all.)  See @(see tame) for a discussion of the various notions of
  tameness.</p>

  <p>Informally, if a formal's ilk is @(':FN'), the corresponding element of
  @('args') must be a tame function symbol or well-formed @('LAMBDA') object.
  If a formal's ilk is @(':EXPR'), the corresponding element of @('args') must
  be a tame expression.</p>

  <p>If a formal has ilk @(':FN') then you are allowed to put a @(tsee lambda$)
  expression in that slot.  Any quoted @('LAMBDA') object you explicitly write
  in such a slot must be well-formed (see @(see well-formed-lambda-objectp)).
  Well-formedness can be hard to achieve in quoted hand-written @('LAMBDA')
  objects; we recommend that you use @('lambda$')!  But the restrictions on
  what can occupy a @(':FN') slot are enforced when user input is translated
  into formal terms.  It is possible to circumvent these syntactic checks
  without endangering soundness: axiomatically @('apply$') puts no restrictions
  on its arguments, it just doesn't behave the way you might expect on
  ill-formed @('LAMBDA') objects.  See @(see
  gratuitous-lambda-object-restrictions).</p>

  <p><b>Clarification</b>: The careful reader will note that the formal
  requirement on a @(':FN') argument is that it must satisfy
  @('tamep-functionp').  Inspection of the definition of @('tamep-functionp')
  reveals that the argument must either be badged symbol with ilks @('T') or
  else be a tame @('LAMBDA') object.  But in the informal description above we
  said that it must be a ``tame function symbol or a <i>well-formed</i>
  @('LAMBDA') object.''  Well-formedness implies tameness but they are not the
  same.  What's going on?  The reason for this and related discrepancies in the
  documentation is that there is a tension between the logical definition of
  @('apply$') and the practical business of executing it.  The former involves
  the existence of a model, soundness, and the difficulty of proving theorems
  about @('apply$').  The latter involves the Common Lisp compiler.  We want
  the logical foundations to be simple so we -- and you -- can reason about
  @('apply$'), but the compiler imposes unavoidable and complicated
  restrictions.  The upshot is that the logical foundations assign meaning to
  @('LAMBDA') objects that cannot be compiled.  Applying merely ``tame''
  @('LAMBDA')s is slower than applying ``well-formed'' ones.  In a sense by
  acting like ``tame @('LAMBDA') objects'' and ``well-formed @('LAMBDA')
  objects'' are the same thing we're trying to trick you!  If you ever have
  occasion to formally express the restrictions on @('apply$') in some theorem,
  use @('tamep-functionp').  But when you write concrete @('LAMBDA') constants,
  try to keep them well-formed.  We try to encourage this by providing
  @(tsee lambda$), which guarantees well-formedness at translate-time, and by
  implementing full well-formedness checks -- not just tameness checks -- on
  quoted @('LAMBDA') objects in @(':FN') slots.  And we give you ways to
  circumvent these checks -- see @(see gratuitous-lambda-object-restrictions)
  -- if you really mean to.</p>")
other
(defxdoc badge-userfn
  :parents (apply$)
  :short "Undefined function used by @('badge') on non-primitives"
  :long "<p>When @(tsee badge) is given a non-primitive function symbol @('fn')
   it calls this function to determine the badge of @('fn').  But this function
   is undefined.  In the proof theory, its value on a given function symbol
   @('fn') is specified, if at all, by the @(tsee warrant) for @('fn') which
   must be available as a hypothesis in the formula being proved.  In the
   evaluation theory, @('badge-userfn') has an attachment that makes it behave
   as though all warrants are assumed.  See @(tsee badge) for details.</p>")
other
(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.")
other
(defxdoc bdd
  :parents (acl2 boolean-reasoning proof-automation)
  :short "Ordered binary decision diagrams with rewriting"
  :long "<p>Note.  The ACL2 bdd capability has been essentially superseded by
 GL; see @(see gl).</p>

 <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>")
other
(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-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>")
other
(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 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 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 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>")
other
(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>")
other
(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'). Thus, the following are theorems.</p>

 @({
  (thm (equal (+ (fix x) y) (+ x y)))
  (thm (equal (+ x (fix y)) (+ x y)))
 })

 <p>Calls of the macro @(tsee +) expand to calls of @('binary-+'); see @(see
 +).</p>")
other
(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)")
other
(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
 rewrite-quoted-constant), @(':')@(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 is similar except that it may use @(tsee state) and @(tsee mfc).
 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'), @('nil'),
 or a non-empty list of variables.  If it is not provided, it defaults to
 @('t'); and it is also treated as @('t') if the value provided is @('nil').
 If it is a non-empty 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 that list of
 variables.  We strongly recommend the use of this list of variables, as that
 list is considered to contribute to the list of variables in the hypotheses of
 a linear rule; see @(see linear), in particular condition (b) mentioned there
 regarding a requirement that maximal terms and hypotheses must suffice for
 instantiating all the variables in the conclusion.  If @('var-list') is @('t')
 (either explicitly or implicitly, as described above), then that condition is
 considered to be met trivially; this could prevent ACL2 from rejecting
 ineffective linear rules.</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>")
other
(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))))
 })")
other
(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)")
other
(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's filename after removing 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>")
other
(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>")
other
(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>")
other
(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.
 See @(see checksum).  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>")
other
(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 certifying 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;
 })")
other
(defxdoc book-name
  :parents (books-tour)
  :short "Conventions associated with book-names"
  :long "@({
  Examples:
  "list-processing"
  "/usr/home/smith/my-arith"
 })

 <p>A <i>book-name</i> is typically a string constant that represents a file.
 (Much later below we discuss other book-names that are not strings, namely,
 @(see sysfile)s; but till then we consider only strings.)  We elaborate book
 names by concatenating the ``connected book directory'' (see @(see cbd))
 string on the left and perhaps a @('".lisp"') ``extension'' 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 relative pathnames without explicit mention of the enclosing
 book's directory.</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 a book-name to include a directory or part of a directory
 name.  Book-names often do not 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 a compiled file extension (like @('".fasl"')) of
 the book-name.</p>

 <p>A book-name is elaborated into a @(see full-book-name) 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>Finally we mention another kind of book-name: a @(see sysfile), which is a
 pair that associates a keyword with a relative pathname.  This kind of
 book-name is used by the implementation, for example in @(see certificate)
 files, but is rarely visible to users.  If you run across a sysfile and want
 to understand more about it, see @(see sysfile).</p>

 <p>See @(see book-contents) to continue the guided tour.</p>")
other
(defxdoc bookdata
  :parents (books)
  :short "Write small files with meta-data about certified @(see books)"
  :long "<p>ACL2 provides a primitive capability for writing out a file of
 metadata 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>Alternatively, one may set environment variable @('ACL2_WRITE_BOOKDATA') to
 any non-empty value to cause @('BK__bookdata.out') to be written, with one
 exception, namely: when the value of state global @('write-bookdata') is
 @(':never').</p>

 <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 @(see full-book-name) of the
 certified book, @('BK'), possibly in @(see sysfile) format.</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 @(see full-book-name)s 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
 })")
other
(defxdoc books
  :parents (top)
  :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 books published about ACL2 and its applications; see
 @(see pubs::pubs-books).</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>")
other
(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-level
 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.  Note: If there is a suitable @('"acl2"')
 executable on your Unix @('PATH') &mdash; for example, if the @('bin')
 subdirectory of the main ACL2 directory is on your @('PATH'), so that
 @('bin/acl2') may be your executable &mdash; then you can omit
 @('"ACL2=..."') below.</p>

 @({
 cd /path/to/acl2-sources/books
 make ACL2=/path/to/acl2-sources/saved_acl2 ...
 })

 <p>For example, the section ``A Full Build'', below, says to do the following
 if you would like to make a change to the @(see community-books) (where the
 @('-j') argument is optional).</p>

 @({
     $ cd /path/to/acl2-sources/books
     $ make ACL2=/path/to/acl2-sources/saved_acl2 -j 2 all
 })

 <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>

 <p>By default, @('make') commands for certifying books take advantage of files
 @('*@useless-runes.lsp').  See @(see useless-runes).</p>

 <h3>Prerequisites</h3>

 <p>We assume that you have already installed ACL2 as per the
 @(see installation-instructions).  In particular, the @(see community-books)
 should be present as the @('books/') subdirectory of your ACL2
 distribution.</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>The instructions below are suitable for ACL2 and all of its experimental
 extensions, e.g., ACL2(p) and ACL2(r).</p>

 <p>It may be preferable to avoid being logged in as root, since developers do
 not test as root and at least one community book
 (@('books/oslib/tests/copy.lisp')) has failed to certify when logged in as
 root.</p>

 <h3>A Basic Build</h3>

 <p>The default @('make') target in @('books/GNUmakefile'), called
 @('basic'), is quite fast &mdash; it excludes many books and certifies only
 the directories listed below, which tend to be widely used.  <b>WARNING</b>:
 This basic build is insufficient for validating
 changes that will go into the @(see community-books); for that, see
 @(see how-to-contribute).</p>

 <ul>
 <li>arithmetic</li>
 <li>arithmetic-3</li>
 <li>arithmetic-5</li>
 <li>@(see ihs)</li>
 <li>misc</li>
 <li>tools (mostly)</li>
 <li>@(see std) (mostly)</li>
 <li>@(see xdoc) (in part)</li>
 <li>data-structures</li>
 <li>apply</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)).  Other books require certain
 additional software.</p>

 <p>The build system will automatically determine which kind of ACL2 you are
 running (ACL2, ACL2(p), or 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.  They are enabled by
 default for all host Lisps except GCL, but you can avoid books that depend on
 Quicklisp libraries by setting @('USE_QUICKLISP=0') in your
 @('make') command.</p>

 <p>Using Quicklisp should definitely work if the host Lisp is CCL or SBCL.
 (Note however that certification of @(see books) that use
 Quicklisp may require @('openssl') to be installed if it is not already
 on your system.)
 There is some chance it will work with Allegro CL, LispWorks, and CMUCL.  It
 will almost certainly <b>not</b> work for GCL (at least as of 2018).</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.</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'), for example as follows.
 (But as noted above, you may omit @('"ACL2=..."') if a suitable executable
 named @('acl2') is on your Unix @('PATH'), such as @('bin/acl2').)</p>

 @({
     $ cd /path/to/acl2-sources/books
     $ make ACL2=/path/to/acl2-sources/saved_acl2 -j 2 all
 })

 <p>This includes a few books that are quite slow to certify.  You can
 exclude those by replacing ``@('all')'' by ``@('regression')'' in the
 command above.</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>")
other
(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 @(see installation).  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 @(see 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 such @('books/workshops/') that is not necessary for certifying the
 most widely-included books.  You can certify just such books as follows.</p>

 @({
  (time nice make basic) >& make-basic.log
 })

 <p>Whether you use target `@('regression')' or target `@('basic')', 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>Alternatively, if you want to cause such deletion and then do a regression,
 simply replace the `@('regression')' target by `@('regression-fresh').</p>

 <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>

 @({
  cert.pl --pcert-all -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>")
other
(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 @(see
 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 @(see 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 (see @(see q)); 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>")
other
(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.")
other
(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>")
other
(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$)")
other
(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)")
other
(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)")
other
(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>")
other
(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').  Note that upon
 returning to the ACL2 read-eval-print loop (for example, using @(':q') if the
 host Lisp is CCL), one will be at the top level even if one had been inside a
 recursive call of @(tsee ld) or a @(see wormhole).</p>

 @(def break$)")
other
(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)
  :monitor! (:rewrite lemma12) t  ; quiet version of :monitor that
                                  ;   invokes :brr t
 })

 <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>")
other
(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>Evaluation of @('(break-on-error :all)') generates a suitable @(see trace)
 of error functions, so that the Lisp debugger is entered whenever ACL2 calls
 them.  You can then continue the interrupted computation by suitable exit from
 the debugger (with a command that depends on the host Lisp).  Evaluation of
 @('(Break-on-error t)'), or equivalently, @('(break-on-error)'), is similar
 except that certain errors are ignored when inside the theorem prover; this is
 probably preferable, in general, to @('(break-on-error :all)').  Finally,
 evaluation of @('(break-on-error nil)') removes those traces.</p>

 <p><b>Remarks</b>.</p>

 <ul>

 <li>The argument, if supplied, is evaluated and must evaluate to @('t'),
 @('nil'), or @(':all').</li>

 <li>For technical reasons, you may see breaks or error messages more than
 once.</li>

 <li>It is an error to call @('break-on-error') while in @(see raw-mode).</li>

 <li>@('Break-on-error') is implemented using ACL2 @(tsee trace!), which is a
 version of @(tsee trace$) that uses a @(see ttag) and hence generates a
 ``@('TTAG NOTE')'' message.  You can use @(':')@(tsee trans1) to see the
 @('trace!') call generated by a given call of @('break-on-error').  Evaluate
 @('(trace$)') if you want to see the current trace specs.</li>

 </ul>

 <p>You are of course 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, to
 consider for inclusion into ACL2.</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>")
other
(defxdoc break-rewrite
  :parents (debugging)
  :short "A version of the ACL2 rewriter with interactive breaks"
  :long "<p>ACL2 allows the user to @(see monitor) the application of @(see
 rewrite), @(see definition), and @(see linear) rules.  When the rewriter is
 about to try to apply an @(tsee enable)d @(see monitor)ed rule, it can trigger
 an interactive break managed by a version of the rewriter called
 &ldquo;break-rewrite&rdquo;.  These breaks can be caused by</p>

 <ul>
 <li>failure of a rewrite rule's equivalence relation
 to be a known refinement of the permitted relations,</li>
 <li>failure of
 a rule's triggering pattern to match the target term while &ldquo;almost&rdquo;
 matching,</li>
 <li>failure to relieve the hypotheses of the rule, or</li>
 <li>failure of any of several heuristic checks to prevent looping in the rewriter.</li>
 </ul>

 <p>From within this read-eval-print loop you can inspect the context, attempt
 to apply the rule, and see what happens.  This interactive loop is technically
 just a call of the standard ACL2 read-eval-print loop, @(tsee ld), on a
 ``@(see wormhole) @(see state)'' (see @(see wormhole)).  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).
 Interactive breaks occur only if the @('break-rewrite') utility is turned
 on (see @(tsee brr)), a monitored rune is being considered by the rewriter,
 and the break conditions specified in the monitor are satisfied (see @(tsee
 monitor)).</p>

 <p>The following utilities can also be helpful for proof @(see debugging).</p>

 <ul>

 <li>@(tsee Dmr) (Dynamically Monitor Rewrites) allows you to watch progress of
 the rewriter in real time.</li>

 <li>The @(see proof-builder) allows you to interactively construct a
 proof.</li>

 <li>@(tsee with-brr-data) helps you to find the source of a term in prover
 output.</li>

 </ul>

 <p>To abort from inside break-rewrite at any time, execute @(':')@(tsee
 a!).</p>

 <p>Output from break-rewrite is abbreviated by default, but that can be
 changed.  See @(see set-brr-evisc-tuple).</p>

 <p>When the break-rewrite facility is turned on (see @(tsee brr)), the
 rewriter performs more sluggishly than when break-rewrite is turned off.
 Therefore if you have done @('(brr t)') to debug a rewriting problem, we
 recommend that you do @('(brr nil)') after the situation is remedied and you
 resume normal proof development.</p>

 <p>For further information, see the related @(':')@(tsee doc) topics listed
 below.</p>

 <p><i>Advice to Developers and Maintainers of ACL2</i>: If you intend to
 modify break-rewrite, we strongly urge you to read the Essay on Break-Rewrite
 in the source code file @('rewrite.lisp').  There we explain the abstraction
 provided by break-rewrite, how it is implemented as a state machine operating
 in a wormhole, and some low-level tools for inspecting the state of
 break-rewrite.  Attempts to add new features without understanding virtually
 everything about the implementation is most likely to create a mess.</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'), an
 interactive read-eval-print loop 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 such a break are
 undone when proceeding from that break (including when proceeding via the
 @(':eval') brr-command).  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.</p>

 <p>There are however exceptions to this loss of state when exiting a break.
 One exception pertains to iprinting (see @(see set-iprint)).  When iprinting
 is enabled in a break, it nevertheless is again disabled upon exiting the
 break.  However, the association of values with iprint indices persists even
 after exiting the break; that is, you can still obtain their values, and if
 you re-enable iprinting then indices will be generated from where they left
 off rather than returning to index 1.  The other exception pertains to setting
 the @(tsee brr-evisc-tuple) while inside break-rewrite: the effects persist.
 See @(tsee set-brr-evisc-tuple).</p>

 <p>When you 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>Exceptions are that @(':')@(tsee ubt) and related commands such as
 @(':')@(tsee ubu), as well as @(tsee puff) and @(tsee puff*), are only allowed
 to touch @(see command)s issued after entering the interactive break.
 (Technical detail: that is because @(tsee disable-ubt) is invoked when
 entering the break.)</p>

 <p>More likely than typing a history 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>The output of the @(':path') command shows a stack of simplification and
 rewriting ``frames'' starting with the current top-level goal (in clausal form
 as a list of literals) and ending with the current target.  Frames should be
 self-explanatory.  Frames describing the attempt to apply a rewrite rule will
 display the name of the equivalence relation the rule uses (unless the
 relation is @('equal')).  All rewrite frames (including the attempt to apply a
 given rewrite rule) will display the current @(see geneqv) (the sense of
 equivalence the rewriter is obligated to maintain) unless the geneqv denotes
 just the @('equal')ity relation.</p>

 <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 at the current depth.  When
 break-rewrite exits it prints ``@('3)')'' (actually, of course, the current
 depth!), closing the parenthesis that opened the current depth, @('3'),
 interaction.  However, between your typing the @(':ok') command and the exit
 from depth @('3') you may well see deeper break-rewrite breaks &mdash;
 triggered by any of your monitored runes &mdash; as the rewriter tries to
 apply the lemma that prompted the current depth @('3') break.</p>

 @({
  :go
 })

 <p>exits break-rewrite without further interaction at the current depth, but
 as it exits it 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
 depth 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 for the current depth @('3').</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) and perhaps the @(see
 linear-arithmetic) @(':pot-list') 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 you then @(':eval') and get
 a break on @('hyp-reliever') you will know it is being used under the attempt
 to apply @('main-lemma').</p>

 <p>However, when the rewriter leaves this attempt to apply @('main-lemma'),
 @('hyp-reliever') will no longer be monitored.  That is, the list of monitored
 runes is maintained as a local variable of break-rewrite.  See @(tsee
 monitored-runes).</p>

 <p>@(':Ok!'), @(':go!'), and @(':eval!') are just like their counterparts
 (@(':ok'), @(':go'), and @(':eval'), respectively), except that before
 proceeding they unmonitor all runes.  Of course, this is only done in the
 scope of the interactive break in which these commands were used.  When
 control returns to the top-level of the ACL2 loop the monitored runes will
 have reverted to its original value there.  These commands allow you to
 proceed from the current depth without getting any deeper breaks.</p>

 <p>@(':Ok$'), @(':go$'), and @(':eval$') are similar but take an additional
 argument which must be a list of runic designators (or a single designator).
 See @(see rune).  Two examples the use of @(':eval$') are</p>

 @({
  3 ACL2 !>:eval$ hyp-reliever
 })

 <p>and</p>

 @({
  3 ACL2 !>:eval$ (hyp-reliever (:definition foo))
 })

 <p>The second command above is exactly equivalent to</p>

 @({
  3 ACL2 !>:monitor hyp-reliever t
  3 ACL2 !>:monitor (:definition foo) t
  3 ACL2 !>:eval
 })

 <p>Analogous remarks apply to @(':go$') and @(':ok$').  If you want to specify
 more sophisticated break criteria (rather than just @(':condition t')) you
 must use the @(':monitor') command explicitly before proceeding.</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 depth).  All the flavors of @(':eval') require
 further interaction after the rule has been tried.</p>

 <p>You are not permitted to &ldquo;re-@(':eval')&rdquo; a rule.  That is,
 after issuing the @(':eval') command in a given break, you cannot issue it
 again in that break.  The rule has been evaluated, the results are available
 to you, and that's that!  All you can do, aside from inspecting the context,
 is allow rewrite to continue, by issuing an @(':ok') or @(':go'), or
 abort.</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 or, equivalently (if you are
 not in a raw Lisp break) use the keyword command @(':a!').  See @(see a!).</p>

 <p>We now address ourselves to the post-@(':eval') interaction with
 break-rewrite.  As noted, post-@(':eval') 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'' that test the context
 of the pending break and that return a list of commands to execute if a break
 occurs; 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 @(':go') or 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
 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>We have not discussed &ldquo;near-miss&rdquo; breaks.  These are caused
 when a monitored rune specifies one of the near-miss break criteria and the
 rune's pattern fails to match the target but &ldquo;almost&rdquo; matches
 according to the criteria.  See @(tsee monitor) for a discussion of near-miss
 break criteria.  But for example, if @('main-lemma') rewrites the term
 @('(f (g (h x) y) x)') and you've installed a monitor on it like this:</p>

 @({
 :monitor main-lemma (:abstraction (f (g u v) w))
 })

 <p>then if the rewriter encountered the target term @('(F (G (MUMBLE A) B)
 C)') it would cause a near-miss break because the pattern of @('main-lemma')
 does not match the target but the specified abstraction of the pattern does
 match the target.</p>

 <p>You interact with a near-miss break just like the breaks described above,
 except some commands (e.g., @(':eval')) are unavailable because the rule did
 not match and thus there is no way to proceed except to exit the break and try
 the next lemma.</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 &mdash; which is why we don't
 write it in typewriter font in this documentation.  Break-rewrite is an
 illusion created by appropriate calls to three ``break point handlers'' named
 @('near-miss-brkpt1'), @('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, the break point handlers are each calls of @(tsee ld)
 running on @(see wormhole) @(see state)s.  They maintain a state machine
 inside the wormhole.  For example, @('brkpt1') is called by rewrite after a
 successful match, if the monitored @(':condition') is true, an interactive
 break occurs.  Upon an @(':ok') or @(':eval'), the wormhole's status
 information is updated, the wormhole is exited (losing any state changes made
 inside the wormhole), rewrite continues to do whatever rewrite does for that
 lemma, and then @('brkpt2') is called.  @('Brkpt2') then uses the state
 information in the wormhole to decide whether to interact or not.</p>

 <p>This helps explain why the rewriter behaves more sluggishly when @('(brr
 t)') has been done: it is entering and exiting wormholes to figure out whether
 to trigger an interactive break.  When you are through with break-rewrite, we
 recommend @('(brr nil)').</p>

 <p>This design causes certain anomalies that might be troubling.</p>

 <p>Suppose you are inside a depth @('3') break before @(':evaling') a
 rule (i.e., you're in the @('brkpt1') @(see wormhole) @(see state)) you define
 some function, @('foo').  Suppose then you @(':eval') the rule and eventually
 control returns to the depth @('3') break (i.e., now you're in the @('brkpt2')
 @(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>See the subtopics listed below to learn more about
 @('break-rewrite').</p>")
other
(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 can expect to see a different
 prompt at the break than you would see in the ACL2 read-eval-print loop.  See
 @(see prompt) for how to change the raw Lisp prompt to emphasize that one is
 in raw Lisp, and hence may wish to quit from the break.</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>")
other
(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>")
other
(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>")
other
(defxdoc brr
  :parents (break-rewrite)
  :short "To enable or disable the breaking of rewrite rules"
  :long "@({
  Example:
  :brr t       ; enable
  (brr t)      ; enable (same as above)
  (brr t t)    ; enable with less output (rarely invoked interactively)
  :brr nil     ; disable

  General Form:
  (brr flg &optional quietp)
 })

 <p>where @('flg') and the optional @('quietp') argument evaluate 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).  For a related proof debugging utility see @(see
 with-brr-data).</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, Console Interrupts, and Subsidiary Prover Calls: 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 break-rewrite environment,
 by executing @('(')@(tsee abort!)@(')').  Otherwise, the normal way to quit
 from such a raw Lisp 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 interrupt or error break happens to occur while ACL2 is
 within a break-rewrite break (in which it is preparing to read @(tsee
 brr-commands)), the abort will merely return to break-rewrite break.  Upon
 exiting that environment, normal theorem proving is continued (and the
 break-rewrite breaks may be entered again in response to subsequent monitored
 rule applications).  In addition, if while in a break-rewrite break, say at
 depth @('d'), you invoke the theorem prover recursively as by typing a @(tsee
 thm) or @(tsee defthm) or @(tsee defun) command to break-rewrite, recursive
 breaks may occur with depths starting at @('d+1').  This can get confusing
 because it may appear that the ongoing (sub-)proofs are part of the original
 proof when in fact the system is just carrying out your commands.</p>")
other
(defxdoc brr-commands
  :parents (break-rewrite)
  :short "@(see Break-Rewrite) Commands"
  :long "<p>Below is a list of commonly used @(see break-rewrite) keyword
  commands.  These are only defined within the breaks caused by @(tsee
  monitor)s on runes in the process of being considered by the ACL2 rewriter.
  These breaks interact with you from within a @(tsee wormhole) and are handled
  by @(tsee ld) (the same function that manages ACL2's top-level interactive
  read-eval-print loop).  So within certain limitations imposed by wormholes,
  you can evaluate any command you would at the top-level of ACL2 in addition
  to the special commands below.</p>

  <p>Many break commands display terms, e.g., the target being rewritten, and
  &ldquo;large&rdquo; terms are &ldquo;eviscerated&rdquo; (i.e., abbreviated)
  before printing.  These commands have corresponding commands suffixed with a
  ``+'' that avoid evisceration so that the terms in question are printed in
  full.  See @(see brr-evisc-tuple).  The notation ``@(':ancestors[+]')'' below
  indicates that the @(':ancestors') command may print abbreviate terms but the
  @(':ancestors+') command does not.</p>

 @({
 :a!                abort to ACL2 top-level
 :ancestors[+]      negations of backchaining hypotheses being pursued
 :btm[+]            bottom-most frame in :path
 :eval              try the rule (i.e., recursively try to relieve
                      the hypotheses and other conditions, possibly
                      producing other breaks) and return to this
                      break afterwards so you can query results
 :eval!             :eval but remove all monitors first (see below)
 :eval$ runes       :eval but first add monitors for runes (see below)
 :explain-near-miss[+]
                    print an explanation of why the rule's pattern failed
                      to match the :target; only relevant in a break caused
                      by a near miss
 :failure-reason[+] reason rule failed (after :eval)
 :final-ttree[+]    ttree after :eval (see :DOC ttree)
 :frame[+] i        ith frame in :path
 :geneqv[+]         generated equivalence relation to be maintained
 :go                :eval but don't return to this break, just
                      print the result of the try
 :go!               :go but first remove all monitors (see below)
 :go$ runes         :go but first add monitors for runes (see below)
 :help              this message
 :hyp i             ith hypothesis of the rule
 :hyps              hypotheses of the rule
 :initial-ttree[+]  ttree before :eval (see :DOC ttree)
 :lhs[+]            left-hand side of rule's conclusion (or, in the case
                      of :rewrite-quoted-constant rules of form [2], the
                      right-hand side!); this is the pattern that the
                      target must match for this :rewrite rule to fire
 :max-term[+]       maximal term of a :linear lemma; this is the pattern
                      that the target must match for this :linear rule to
                      fire
 :ok                like :go, but don't print the result of the try
 :ok!               :ok but first remove all monitors (see below)
 :ok$ runes         :ok but first add monitors for runes (see below)
 :path[+]           rewriter's path from top clause to :target
 :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
 :pot-list[+]       set of polynomials governing :target,
                      organized by maximal term
 :rewritten-rhs[+]  rewritten :rhs (after :eval) of a rewrite rule
 :rhs               right-hand side of rule's conclusion (or, in the case
                      of :rewrite-quoted-constant rules of form [2], the
                      left-hand side!)
 :standard-help     :help message from ACL2 top-level
 :target[+]         term being rewritten
 :top[+]            top-most frame in :path
 :type-alist[+]     type assumptions governing :target
 :unify-subst[+]    substitution making :lhs equal :target
 :wonp              indicates whether application succeeded (after :eval)
 })

 <p>The form @('(')@(tsee brr@)@(' :cmd)'), when evaluated within a break,
 will return the value that is only printed by certain of the keyword commands
 above.  This is particularly useful when programming break conditions.  See
 @(tsee monitor).</p>

 <p>Since you're actually in a general read-eval-print loop when interacting
 with @(see break-rewrite) you may type the usual ACL2 commands like
 @(':')@(tsee pbt) or @(':')@(tsee pe) or even @(tsee defun) and @(tsee
 defthm).  You cannot modify @(see stobj)s or files from within the break.
 However, all @(see state) changes you cause from within @(see break-rewrite)
 are lost when you exit or @(':eval') the rule.</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').  The pattern used to fire a linear
 rule is found with the command @(':max-term').  In addition,
 @(':rewritten-rhs') also does not apply to linear rules, 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>

 <p>See the discussion of form [2] @(':')@(tsee rewrite-quoted-constant) rules
 for an explanation of the swapped meanings of ``@(':lhs')'' and
 ``@(':rhs').''</p>

 <p>The commands @(':eval$'), @(':go$'), and @(':ok$') take an argument, called
 runes, which may be a list of runes and/or runic designators (see @(see rune))
 or a single rune or runic designator.  For each rune in runes, these commands
 execute @(':')@(tsee monitor) rune @('t'), and then execute @(':eval'),
 @(':go') or @(':ok') as appropriate.</p>

 <p>This is useful if you want to monitor the use of a &ldquo;secondary&rdquo;
 rune only during the attempt to apply a &ldquo;primary&rdquo; rune: install
 the monitor on the secondary rune inside the break caused by the primary rune.
 In the case of @(':eval$'), when the attempt to apply the primary rune is
 finished you will be back in the interactive break and can inspect the
 results.  You will notice that the secondary rune is still on the list of
 @(tsee monitored-runes).  However, when you exit that break
 @('monitored-runes') will be restored to its earlier value.  In the case of
 @('go$') and @('ok$'), no interactive break occurs after the primary rune has
 been applied.</p>

 <p>Similar remarks apply to @(':eval!'), @(':go!'), and @(':ok!') except they
 first @(':')@(tsee unmonitor) @(':all'), before proceeding with the
 appropriate @(':eval'), @(':go'), or @(':ok').  These commands are useful if
 you want no breaks to occur while attempting to apply the rune that caused the
 current break.</p>

 <p>Recall (from the discussion of @(tsee monitor)s) that break conditions
 terms installed as part of break criteria do not just determine whether a
 break occurs but can compute the initial break commands fed to the interactive
 loop.  Thus, for example, you can install a monitor that causes the rewriter
 to not only break when a certain rune is used, but then automatically print
 information, proceed from the break, inspect the result, and then either exit
 the break or prompt for user input.  See the discussion in @(tsee
 monitor).</p>

 <p>Note: If you use commands that change the monitored runes during a break,
 e.g., @(tsee monitor), @(tsee unmonitor), or @(':eval!'), @(':eval$'), etc.,
 then abort during the recursion, the list of monitored runes will not
 necessarily be restored to its original top-level setting.</p>")
other
(defxdoc brr-evisc-tuple
  :parents (brr evisc-tuple)
  :short "Determines partial suppression of output from @(see brr-commands)"
  :long "<p>See @(see evisc-tuple) for relevant background on ``evisceration'':
 eliding of subexpressions during printing.  Also see @(see break-rewrite) for
 background on the break-rewrite loop.</p>

 @({
 General Form:
 (brr-evisc-tuple state)
 })

 <p>The value of this function is used as the evisceration tuple by @(see
 brr-commands).  The value can be changed with @(tsee set-brr-evisc-tuple) or
 the more general @(tsee set-evisc-tuple).</p>

 <p>A special value, @(':default'), is legal for this evisc-tuple, and is its
 initial value.  In that case the actual evisc-tuple used during output from
 @(see brr-commands) &mdash; which we call the <i>effective value</i> of the
 @('brr-evisc-tuple') &mdash; is the value of the evisc-tuple for terms.  See
 @(see set-evisc-tuple), in particular, the discussion of the @(':term') site
 for setting evisc-tuples.</p>

 <p>Think of @('brr-evisc-tuple') as a true global variable, not a locally
 bound variable of break-rewrite.  In particular, if you set the
 @('brr-evisc-tuple') inside a break-rewrite interactive break and eventually
 exit that break &mdash; either to enter a deeper break or return to a
 shallower break or to the ACL2 top-level &mdash; the @('brr-evisc-tuple') will
 retain its chronologically most recent setting.</p>

 <p>The @('brr-evisc-tuple') is used when @(see break-rewrite) prints its
 banner opening or closing a break on some monitored rune and when certain
 @(see brr-commands) print their results.</p>

 <p>When you're in a break-rewrite break, you're actually dealing with the
 read-eval-print loop managed by @(tsee ld).  It prints its results using the
 @(tsee ld-evisc-tuple), while @(tsee brr-commands) use @('brr-evisc-tuple').
 This can cause some confusion.</p>

 <p>For example, suppose you have set the @('brr-evisc-tuple') to
 @('(evisc-tuple 2 3 nil nil)') so break-rewrite banners and brr-commands only
 print to depth 2 and length 3.  Suppose the target term is @('(F (G (H 1)) 2 3
 4 5 6 7)').  Then the following interaction with break-rewrite could
 occur:</p>

 @({
 3 ACL2 >:target
 (F (G #) 2 ...)
 3 ACL2 >(make-list 10)
 (NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL)
 })

 <p>You might ask ``Given that the @('brr-evisc-tuple') limits the print length
 to @('3'), which I see when I print @(':target'), how come the @('make-list')
 showed all 10 elements?''  The answer is that the @('brr-command')
 @(':target') actually printed the target with the @('brr-evisc-tuple') and
 returned @('(value :invisible)') which @('ld')'s read-eval-print loop doesn't
 print.  But the @('make-list') returned a list of length ten and the
 read-eval-print loop printed it using the @(tsee ld-evisc-tuple).</p>

 <p>Another issue relating @('brr-evisc-tuple') and @('ld-evisc-tuple') is that
 while @('brr-evisc-tuple') is a true global, retaining its chronologically
 most recently set value at all depths of break-rewrite, @('ld-evisc-tuple') is
 locally bound by break-rewrite (actually, by the @('ld') in @('wormhole')) and
 so sees its value restored as break-rewrite ascends back toward the top-level
 of ACL2.</p>")
other
(defxdoc brr-near-missp
  :parents (break-rewrite)
  :short "attachable function for determining &ldquo;near misses&rdquo;"
  :long "<p>This is a system function that determine whether a failed match of
  a monitored rule constitutes a near miss.</p>

  <p><b>Note:</b>This function is attachable (see @(see defattach)).</p>

  @({
  General Form:
  (brr-near-missp msgp lemma target rcnst criteria-alist)
  })

  <p>where msgp is @('t') or @('nil'), @('lemma') is the ACL2 record
  representing a @(tsee monitor)ed @(':rewrite') rule or @(':linear') rule,
  @('target') is a term to which the rewriter tried to apply the rule but
  failed to match the pattern in the lemma, @('rcnst') is the rewrite constant
  at the time of the attempt, and @('criteria-alist') is a symbol-alist
  associated with the rule in @(tsee monitored-runes).</p>

  <p>The function determines whether the pattern of the lemma
  &ldquo;almost&rdquo; matches the target, i.e., whether a &ldquo;near
  miss&rdquo; has occurred.  The function is only called if the exact match
  failed.  The built-in version of this function checks the criteria described
  in @(tsee monitor).  If a near miss has occurred, the result is either @('t')
  or a message (see @(tsee msg)) object describing the near miss.  If a near
  miss did not occur, the result is @('nil').  See the source code for
  @('built-in-brr-near-missp') for details of how the built-in version of this
  function operates.</p>")
other
(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.  For background on the notion of
 ``translated'' term, see @(see term).</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.

  :pot-list        *  the pot-list, which is the set of polynomials
                      that are assumed in the current context,
                      organized by maximal term.  Each polynomial in
                      the list is a linear-pot record.

  :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.

  :geneqv          *  the generated equivalence relation that specifies
                      what equivalence relations may be used to rewrite
                      the target.  (See the documentation for geneqv and
                      refinement-failure.)

  :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>")
other
(defxdoc built-in-clause
  :parents (rule-classes)
  :short "To build a @(see 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 @(see clause)s 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>")
other
(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 are theorems.</p>

 @({
  (implies (and (integerp n)
                (<= 0 n)
                (true-listp l))
           (equal (length (butlast l n))
                  (if (< n (length l))
                      (- (length l) n)
                    0)))

  (equal (len (butlast l n)) (nfix (- (len l) (nfix n)))))
 })

 <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)")
other
(defxdoc caaaar
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee caaar)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc caaadr
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee caadr)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc caaar
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee caar)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc caadar
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee cadar)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc caaddr
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee caddr)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc caadr
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee cadr)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc caar
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee car)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc cadaar
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee cdaar)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc cadadr
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee cdadr)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc cadar
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee cdar)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc caddar
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee cddar)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc cadddr
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee cdddr)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc caddr
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee cddr)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc cadr
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee cdr)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(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 that is an error.</p>

 <p>Specifically: ACL2 will cause an error in the following two
 circumstances:</p>

 <ul>

 <li>when calling @(tsee ld) inside @(tsee progn!) unless state global
 @('ld-okp') is first set to @('t'), e.g., using @('(assign ld-okp t)');
 also,</li>

 <li>when calling @('ld') while inside raw Lisp, e.g., when loading a compiled
 file during an invocation of @(tsee include-book).</li>

 </ul>

 <p>Consider for example the following book, where file @('const.lsp') contains
 the single form @('(defconst *foo* '(a b))') after its initial @(tsee
 in-package) form.</p>

 @({
 (in-package "ACL2")
 (defttag t)
 (progn! (ld "const.lsp"))
 })

 <p>An attempt to certify this book as follows</p>

 @({
 (certify-book "const-wrapper" 0 t :ttags :all)
 })

 <p>will cause an error:</p>

 @({
 ACL2 Error in LD:  It is illegal to call LD in this context.  See :DOC
 calling-ld-in-bad-contexts.
 })

 <p>However, that error can be avoided by expanding the @(tsee progn!) call as
 follows.</p>

 @({
 (progn! (assign ld-okp t)
         (ld "const.lsp"))
 })

 <p>Now certification succeeds; however, any subsequent call of @(tsee
 include-book) will fail to load the compiled file for the book.  Again, that
 is necessary because of how ACL2 is designed; in this case, the @(tsee ld)
 call would interfere with tracking of constant definitions when loading the
 compiled file for the book.  To avoid warnings about loading compiled files,
 either certify the book without creating a compiled file or else include the
 book without loading the compiled file; see @(see certify-book) and @(see
 include-book).</p>

 <p>Note that it is legal to put a definition such as the following into a
 book, where @('ld') is called in the body of a function; the two conditions
 above do not prohibit this.</p>

 @({
 (defun foo (state)
   (declare (xargs :guard t :stobjs state :mode :program))
   (ld '((defun h (x) x)) :ld-user-stobjs-modified-warning t))
 })

 <p>One can then include the book, evaluate @('(foo state)'), and then evaluate
 calls of @('h').</p>")
other
(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>")
other
(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>")
other
(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
 to test equality, as described below..</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; if
 neither is present, then an equivalent expression results from adding the
 final case @('(t nil)').</p>

 <p>As suggested above, each case @('(xi val-i)') generates an if-then-else
 expression as follows.  If @('xi') is a non-nil atom (i.e., @('xi') is not
 @('nil') or a cons pair), then that case generates the expression @('(if (eql
 expr (quote xi)) vali ...)')  where `@('...')' denotes the expression
 generated by the rest of the cases.  If however @('xi') is a list, then
 instead the generated expression is @('(if (member expr (quote xi)) vali
 ...)').  The final case @('(t val-k+1)') or @('(otherwise val-k+1)') generates
 @('val-k+1').  Note that @('t') and @('otherwise') here must be in the
 @('"ACL2"') package.  Also note that to compare @('expr') with @('nil'), you
 should write the case as @('((nil) val-i)') rather than @('(nil val-i)')
 &mdash; and similarly for @('t') or @('otherwise') &mdash; that is, put the
 symbol in a list.</p>

 <p>@('Case') is defined in Common Lisp.  See any Common Lisp documentation for
 more information.</p>")
other
(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 symbol, the @('pati') are structural patterns as
 described below, each &ldquo;@('dcli ...')&rdquo; indicates 0 or more @(tsee
 declare) forms, and the @('bodyi') are terms.  The legal @('declare') forms
 are the same as for @(tsee let): @('ignore'), @('ignorable'), and @('type').
 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*, :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.  This is the same as (QUOTE obj).
  (QUOTE~ sym)    where sym is a symbol, is like (QUOTE sym) except it
                    matches any symbol with the same symbol-name as sym.
                    Note that QUOTE~ is in the "ACL2" package.
 })

 <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>

 <p>Technical point: The symbol @('sym') referenced by the symbol @('!sym') is
 in the same package as @('!sym') but with the leading exclamation point
 character, @('\#!'), removed from the @(tsee symbol-name) of @('!sym').</p>")
other
(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)")
other
(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 @(see clause)s 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 the goal above.  Thanks!]

 This simplifies, using trivial observations, to

 [Note:  A hint was supplied for 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>")
other
(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 (``cbd'') is a string ending with the @('/')
 character that specifies a directory as an absolute pathname.  (See @(see
 pathname) for a discussion of file naming conventions.)  When utilities that
 take a filename argument, such as @(tsee include-book), are given a relative
 pathname, it is elaborated into an absolute pathname, essentially by
 appending the connected book directory string to the left and @('".lisp"')
 to the right.  (This absolute pathname is actually canonical when elaborating
 book names.  For more details on book names, see @(see book-name) and also see
 @(see full-book-name).)  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>

 <p>Note that the cbd is used for elaborating every @(see pathname) argument,
 not just a pathname that represents a book.  (Technical remark: Some
 utilities, such as @(tsee open-input-channel), use the cbd indirectly as
 follows.  That utility uses the Common Lisp utility, @('open'), which knows
 nothing about the cbd.  However, ACL2 arranges that the Lisp global
 @('*default-pathname-defaults*') always has the cbd as its value, and Lisp
 uses that global to elaborate relative pathnames much as ACL2 uses the
 cbd.)</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>For example, if the @('cbd') is @('"/usr/home/smith/"') then the @(see
 book-name) @('"project/task-1/arith"') is elaborated using the @('cbd') to
 the @(see full-book-name) @('"/usr/home/smith/project/task-1/arith.lisp"'),
 which 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).</p>

 <p>As noted above, 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>")
other
(defxdoc ccl-installation
  :parents (obtaining-common-lisp)
  :short "Installing Clozure Common Lisp (CCL)"
  :long "<p>For those who use ACL2 built on CCL as the host Common Lisp
 implementation, it has been common practice to use the latest GitHub version
 of CCL.  We provide the following instructions for you to choose from.  The
 ``brief'' instructions for Linux or Mac (according to your operating system)
 might well suffice; the ``elaborate'' instructions have helped with version
 control.</p>

 <ul>

 <li>@(see ccl-installation-linux-brief)</li>

 <li>@(see ccl-installation-mac-brief)</li>

 <li>@(see ccl-installation-linux-elaborate)</li>

 <li>@(see ccl-installation-mac-elaborate)</li>

 </ul>

 <p>You may prefer instead to look at the <a
 href='https://github.com/Clozure/ccl/releases'>CCL Releases</a> page, which
 has potentially more up-to-date information; then you can use the links above
 only as needed (e.g., for Linux-specific information or for discussion of
 @('CCL_DEFAULT_DIRECTORY')).</p>

 <p>One of the links listed above should generally suffice.  But if you
 would like additional information on CCL installation and implementation, see
 @(see ccl-installation-extra).</p>")
other
(defxdoc ccl-installation-extra
  :parents (ccl-installation)
  :short "Clozure Common Lisp (CCL) installation and implementation details"
  :long "<p><b>NOTE</b>: See <a
 href='https://github.com/Clozure/ccl/releases/'>the Clozure CL releases
 page</a> for the latest information, which may supersede some of what is
 included below.</p>

 <p>This topic, contributed by Warren A. Hunt, Jr., extends the basic
 information given in @(see ccl-installation).  It may be useful to some,
 especially those who use ACL2 in ways that particularly stress memory.
 Another resource may be found on <a
 href='https://github.com/Clozure/ccl/releases/'>this page</a>.</p>

 <p>Below we provide instructions to build CCL on FreeBSD and MacOS; building
 on Linux will be similar.  Before providing the build instructions, we mention
 a few facts about CCL's implementation.</p>

 <p>CCL's implementation can't expand stack space automatically.  The sizes of
 various stacks are set at thread creation time.  Most programs don't need very
 big stacks.  The CCL default value and temp stack sizes may be too small for
 compute-intensive applications.</p>

 <p>The various stack sizes are set when creating a thread with code in
 @('CCL::MAKE-PROCESS') and @('CCL::PROCESS-RUN-FUNCTION'), and they set the
 three stack sizes of the initial listener thread that is created when CCL
 starts.</p>

 <p>The value stack is used for data in deeply-nested lisp recursion.  ACL2 can
 benefit from an increase in the size of the value stack.</p>

 <p>The temp stack is used for dynamic-extent objects.  This might need need to
 be larger than the default.</p>

 <p>The control stack is used to run C and binary code; it would be surprising
 to need to increase its size.</p>

 <p>If only one or two threads are needed, giant (e.g., 4 GB) stacks can
 be OK, but with many threads large stacks use lots of memory.  Below
 are the stacks along with their current (April, 2020) default sizes.</p>

  @({
  ccl::*default-control-stack-size*                    ;; default 2^21
  ccl::*initial-listener-default-control-stack-size*   ;; default 2^21

  ccl::*default-value-stack-size*                      ;; default 2^21
  ccl::*initial-listener-default-value-stack-size*     ;; default 2^21

  ccl::*initial-listener-default-temp-stack-size*      ;; default 2^20
  ccl::*default-temp-stack-size*                       ;; default 2^20
  })

 <p>If we are running on a 32-bit platform, we set the stack sizes modestly.
 If we are on a 64-bit platform, we set the stack sizes to much larger
 values.  See the later discussion about ``configure-ccl.lisp'' below to
 see how to alter (increase) stack sizes.</p>

 <h3>MacOS Build Instructions:</h3>

 @({
 git clone https://github.com/Clozure/ccl.git ccl-dev
 curl -L -O https://github.com/Clozure/ccl/releases/download/v1.12-dev.5/darwinx86.tar.gz
 cd ccl-dev ; tar xf ../darwinx86.tar.gz
 })

 <p>Rebuild C-based, Lisp kernel</p>

 <p>To rebuild the Lisp-code part of the kernel, do...</p>

 @({
 cd lisp-kernel/darwinx8664 ; make ; cd ../..
 })

 <p>Unlike for FreeBSD and Linux, we exclude ``:full t'' from the
 ``rebuild-ccl'' command just below Matt Emerson (a CCL expert) writes:</p>

 <blockquote>

 <p>After looking at your log, I was able to duplicate the problem myself.
 For some reason I do not understand, it appears that on Catalina,
 removing the running lisp kernel binary causes run-program to break
 (trying to run external programs gets signal 9).  This surprises me
 very much.</p>

 <p>One of the effects of running (rebuild-ccl :full t), is that it first does
 a "make clean" in the lisp kernel directory, and then does a regular make.
 This has worked for years, and I do not know why it has stopped working.</p>

 </blockquote>

 <p>To avoid this, rebuild the lisp with (rebuild-ccl :clean t) instead.  Do
 not specify ``@(':full t')''.  Since you have already built the lisp kernel,
 you gain nothing from ``@(':full t')'' doing it again.  So, once the C-based,
 Lisp kernel is built, then do:</p>

 @({
 echo "(in-package :ccl) (rebuild-ccl :verbose t :clean t)" | \
       ./dx86cl64 -n |& tee ./ccl-build-compile.log
 })

 <p>Matt Emerson suggests that one re-build again.  We asked Matt a
 long-simmering question: we have been told that it is a good idea to compile
 CCL twice.  Is that so that the CCL compiler produced by pass one on the
 target system is used to compile the CCL system that will be used (on the
 target system)?  Or, is compiling twice some silly myth?  Matt Emerson
 responded:</p>

 <blockquote>

 <p>It's not entirely mythic.  Some rare changes do need the lisp to be rebuilt
 twice for bootstrapping purposes, but usually it isn't required.</p>

 </blockquote>

 <p>Thus, we recommend you re-build (compile) the Lisp code again.</p>

 @({
 echo "(in-package :ccl) (rebuild-ccl :verbose t :clean t)" | \
       ./dx86cl64 -n |& tee ./ccl-build-compile-2.log
 })

 <p>Finally, one may specialize the final image by:</p>

 @({
 cat configure-ccl.lisp | ./dx86cl64 -n |& tee ~/ccl-build-specialize.log
 })

 <p>where ``configure-ccl.lisp'' (not supplied) contains whatever CCL
 specialization commands you wish to have in the version of CCL you use for
 ACL2 or other work.  See the end of this note for an example of
 ``configure-ccl.lisp''.</p>

 <h3>FreeBSD Build Instructions:</h3>

 <p>The FreeBSD build instructions are similar to the MacOS build instruction,
 but the names are changed appropriately.</p>

 @({
 git clone https://github.com/Clozure/ccl.git ccl-dev
 curl -L -O https://github.com/Clozure/ccl/releases/download/v1.12-dev.5/freebsd12-x8664.tar.gz
 cd ccl-dev
 tar xf ../freebsd12-x8664.tar.gz
 })

 <p>Rebuild C-based Lisp kernel</p>

 @({
 cd lisp-kernel/freebsdx8664 ; make ; cd ../..
 })

 <p>To rebuild the Lisp-code part of the kernel, do...</p>

 @({
 echo "(in-package :ccl) (rebuild-ccl :full t :verbose t :clean t)" | \
       ./fx86cl64 -n |& tee ./ccl-build-compile.log
 })

 <p>FreeBSD is OK with the ``:full t'' flag, which as of MacOS 10.15
 breaks (but used to work on earlier versions of MacOS).  So, this
 option persists on the FreeBSD build.</p>

 <p>Matt Emerson recommends building the Lisp code a second time; see
 the ``MacOS Build Instructions'' above for his rationale.</p>

 @({
 echo "(in-package :ccl) (rebuild-ccl :full t :verbose t :clean t)" | \
       ./fx86cl64 -n |& tee ./ccl-build-compile-2.log
 })

 <p>Finally, one may specialize the final image by:</p>

 @({
 cat ~/a/scripts/configure-ccl.lisp | ./fx86cl64 -n |& tee ~/ccl-build-specialize.log
 })

 <p>where ``configure-ccl.lisp'' (not supplied) contains whatever CCL
 specialization commands you wish to have in the version of CCL you use for
 ACL2 or other work.</p>

 <code><h3>configure-ccl.lisp</h3></code>

 <p>Sample ``configure-ccl.lisp'' file for 64-bit implementation:</p>

 @({
 (progn
   ;; Parameters to configure CCL for use on FreeBSD and MacOS

   (in-package :ccl)

   ;; Enlarge stack sizes
   (setq *default-value-stack-size*                    (expt 2 28))
   (setq *initial-listener-value-stack-size*           (expt 2 28))

   (setq *default-temp-stack-size*                     (expt 2 24))
   (setq *initial-listener-temp-stack-size*            (expt 2 24))

   (setq *default-control-stack-size*                  (expt 2 24))
   (setq *initial-listener-default-control-stack-size* (expt 2 24))

   ;; For CCL double precision
   (setf *read-default-float-format* 'double-float)

   ;; Make DEFUN save the source code for later recovery via
   ;; FUNCTION-LAMBDA-EXPRESSION.
   (setq *save-definitions* t)
   (setq *fasl-save-definitions* t)

   ;; Make GC verbose; see ACL2 documentation topic GC-VERBOSE.
   (gc-verbose t t)

   ;; Dump executable heap image; see ACL2 documentation topic SAVE-EXEC.
   (save-exec *heap-image-name* "Modification string to print at startup")
   )
 })")
other
(defxdoc ccl-installation-linux-brief
  :parents (ccl-installation)
  :short "Installing Clozure Common Lisp (CCL) on Linux (brief version)"
  :long "<p><b>NOTE:</b> See <a
 href='https://github.com/Clozure/ccl/releases/'>the Clozure CL releases
 page</a> for the latest information, which probably supersedes what is
 included below.</p>

 <p>See @(see ccl-installation) for introductory remarks.  The instructions
 below describe how to install CCL on Linux.  For more elaborate ``cookbook''
 instructions see @(see ccl-installation-linux-elaborate).</p>

 <p><b>Note</b>: Linux users may need to install m4.</p>

 <p>Fetch CCL from GitHub into a fresh subdirectory, @('ccl/').</p>

 @({
 git clone https://github.com/Clozure/ccl
 })

 <p>Next fetch and extract a development snapshot in the new @('ccl')
 directory.  <b>WARNING.</b>  The version below is current as of this
 writing (November, 2023), but see <a
 href='https://github.com/Clozure/ccl/releases/'>https://github.com/Clozure/ccl/releases/</a>
 for the latest snapshots; in particular, @('"v1.12.2"') below could change,
 e.g., to @('"v1.12.3"') or @('"v1.13"').</p>

 @({
 cd ccl
 wget https://github.com/Clozure/ccl/releases/download/v1.12.2/linuxx86.tar.gz
 tar xfz linuxx86.tar.gz
 })

 <p>Rebuild and quit, twice.</p>

 @({
 echo '(rebuild-ccl :full t)' | ./lx86cl64
 echo '(rebuild-ccl :full t)' | ./lx86cl64
 })

 <p>Create the following executable script, which you will probably want to
 name @('"ccl"'), where @('<DIR>') is the absolute pathname (without using
 ``@('~')'') of the directory in which you issued the ``@('git clone')''
 command.  Place this script wherever you wish, though putting it in a
 directory on your Unix @('PATH') might be helpful (since then you can invoke
 it as, say @('"ccl"')).</p>

 @({
 #!/bin/sh

 export CCL_DEFAULT_DIRECTORY=<DIR>/ccl
 ${CCL_DEFAULT_DIRECTORY}/scripts/ccl64 "$@"
 })

 <p>You're done!  (Note however that certification of @(see books) that use
 @(see Quicklisp) may require @('openssl') to be installed if it is not already
 on your system.)</p>")
other
(defxdoc ccl-installation-linux-elaborate
  :parents (ccl-installation)
  :short "Installing Clozure Common Lisp (CCL) on Linux (elaborate version)"
  :long "<p><b>NOTE:</b> See <a
 href='https://github.com/Clozure/ccl/releases/'>the Clozure CL releases
 page</a> for the latest information, which may well supersede what is included
 below.</p>

 <p>See @(see ccl-installation) for introductory remarks.  The ``cookbook''
 instructions below give you one way to install CCL on Linux without any
 knowledge of git or CCL.  For more streamlined instructions see @(see
 ccl-installation-linux-brief).</p>

 <p><b>Note</b>: Linux users may need to install m4.</p>

 <p>First fetch CCL from GitHub as follows.  (You may prefer to use ``@('git
 pull')'' if you previously did this step.  In that case you probably won't
 want to do the optional renaming of the directory, mentioned below.)</p>

 @({
 # Obtain a ccl distribution in a fresh directory:
 mkdir temp
 cd temp
 git clone https://github.com/Clozure/ccl
 # Optionally rename that directory as suggested below, after
 # executing the following three commands.
 cd ccl
 git rev-parse HEAD
 cd ../../
 # Optionally change directory name, and then go back to ccl directory:
 # You'll want the last 10 hex digits to match those of the
 # output from the ``git rev-parse HEAD'' command above: do
 # that twice here and once further below.
 mv temp 2017-12-07-6be8298fe5
 cd 2017-12-07-6be8298fe5/ccl
 })

 <p>Next fetch and extract a development snapshot in the new @('ccl')
 directory.  <b>WARNING.</b>  The version below is current as of this
 writing (November, 2023), but see <a
 href='https://github.com/Clozure/ccl/releases/'>https://github.com/Clozure/ccl/releases/</a>
 for the latest snapshots; in particular, @('"v1.12.2"') below could change,
 e.g., to @('"v1.12.3"') or @('"v1.13"').</p>

 @({
 wget https://github.com/Clozure/ccl/releases/download/v1.12.2/linuxx86.tar.gz
 tar xfz linuxx86.tar.gz
 })

 <p>Rebuild and quit, twice.</p>

 @({
 echo '(rebuild-ccl :full t)' | ./lx86cl64
 echo '(rebuild-ccl :full t)' | ./lx86cl64
 })

 <p>Create an executable script like the following.  You might want to call it
 ``@('ccl')'' and put it into a directory on your path.  Be sure to change the
 name (shown as ``2017-12-07-6be8298fe5'' above) to match the name change
 already made above.</p>

 @({
 #!/bin/sh

 export CCL_DEFAULT_DIRECTORY=/projects/acl2/lisps/ccl/2017-12-07-6be8298fe5/ccl
 ${CCL_DEFAULT_DIRECTORY}/scripts/ccl64 "$@"
 })

 <p>Now ensure that your script is executable, e.g.:</p>

 @({
 chmod +x my-script
 })

 <p>You're done!  (Note however that certification of @(see books) that use
 @(see Quicklisp) may require @('openssl') to be installed if it is not already
 on your system.)</p>")
other
(defxdoc ccl-installation-mac-brief
  :parents (ccl-installation)
  :short "Installing Clozure Common Lisp (CCL) on Mac (brief version)"
  :long "<p><b>NOTE:</b> See <a
 href='https://github.com/Clozure/ccl/releases/'>the Clozure CL releases
 page</a> for the latest information, which probably supersedes what is
 included below.</p>

 <p>See @(see ccl-installation) for introductory remarks.  The instructions
 below describe how to install CCL on a Mac (Darwin).  For more elaborate
 ``cookbook'' instructions see @(see ccl-installation-mac-elaborate).</p>

 <p>Fetch CCL from GitHub into a fresh subdirectory, @('ccl/').</p>

 @({
 git clone https://github.com/Clozure/ccl
 })

 <p>Next fetch and extract a development snapshot in the new @('ccl')
 directory.  <b>WARNING.</b>  The version below is current as of this
 writing (November, 2023), but see <a
 href='https://github.com/Clozure/ccl/releases/'>https://github.com/Clozure/ccl/releases/</a>
 for the latest snapshots; in particular, @('"v1.12.2"') below could change,
 e.g., to @('"v1.12.3"') or @('"v1.13"').</p>

 @({
 cd ccl
 curl -O -L https://github.com/Clozure/ccl/releases/download/v1.12.2/darwinx86.tar.gz
 tar xfz darwinx86.tar.gz
 })

 <p>Rebuild the lisp kernel by hand before trying to rebuild the lisp.</p>

 @({
 cd lisp-kernel/darwinx8664; make clean; make
 cd -
 })

 <p>Rebuild and quit, twice.</p>

 @({
 echo '(rebuild-ccl :clean t)' | ./dx86cl64
 echo '(rebuild-ccl :clean t)' | ./dx86cl64
 })

 <p>Create the following executable script, which you will probably want to
 name @('"ccl"'), where @('<DIR>') is the absolute pathname (without using
 ``@('~')'') of the directory in which you issued the ``@('git clone')''
 command.  Place this script wherever you wish, though putting it in a
 directory on your Unix @('PATH') might be helpful (since then you can invoke
 it as, say @('"ccl"')).</p>

 @({
 #!/bin/sh

 export CCL_DEFAULT_DIRECTORY=<DIR>/ccl
 ${CCL_DEFAULT_DIRECTORY}/scripts/ccl64 "$@"
 })

 <p>You're done!  (Note however that certification of @(see books) that use
 @(see Quicklisp) may require @('openssl') to be installed if it is not already
 on your system.)</p>")
other
(defxdoc ccl-installation-mac-elaborate
  :parents (ccl-installation)
  :short "Installing Clozure Common Lisp (CCL) on Mac (elaborate version)"
  :long "<p><b>NOTE:</b> See <a
 href='https://github.com/Clozure/ccl/releases/'>the Clozure CL releases
 page</a> for the latest information, which may well supersede what is included
 below.</p>

 <p>See @(see ccl-installation) for introductory remarks.  The ``cookbook''
 instructions below give you one way to install CCL on a Mac
 (Darwin) without any knowledge of git or CCL.  For more streamlined
 instructions see @(see ccl-installation-mac-brief).</p>

 <p>First fetch CCL from GitHub as follows.  (You may prefer to use ``@('git
 pull')'' if you previously did this step.  In that case you probably won't
 want to do the optional renaming of the directory, mentioned below.)</p>

 @({
 # Obtain a ccl distribution in a fresh directory:
 mkdir temp
 cd temp
 git clone https://github.com/Clozure/ccl
 # Optionally rename that directory as suggested below, after
 # executing the following three commands.
 cd ccl
 git rev-parse HEAD
 cd ../../
 # Optionally change directory name, and then go back to ccl directory:
 # You'll want the last 10 hex digits to match those of the
 # output from the ``git rev-parse HEAD'' command above: do
 # that twice here and once further below.
 mv temp 2017-12-07-6be8298fe5
 cd 2017-12-07-6be8298fe5/ccl
 })

 <p>Next fetch and extract a development snapshot in the new @('ccl')
 directory.  <b>WARNING.</b>  The version below is current as of this
 writing (November, 2023), but see <a
 href='https://github.com/Clozure/ccl/releases/'>https://github.com/Clozure/ccl/releases/</a>
 for the latest snapshots; in particular, @('"v1.12.2"') below could change,
 e.g., to @('"v1.12.3"') or @('"v1.13"').</p>

 @({
 curl -L -O https://github.com/Clozure/ccl/releases/download/v1.12.2/darwinx86.tar.gz
 tar xfz darwinx86.tar.gz
 })

 <p>Rebuild the lisp kernel by hand before trying to rebuild the lisp.
 (Note: This step was formerly unnecessary and might become unnecessary again,
 but it seems to have been necessary on MacOS Catalina (10.15).</p>

 @({
 cd lisp-kernel/darwinx8664; make clean; make
 cd -
 })

 <p>Rebuild and quit, twice.</p>

 @({
 echo '(rebuild-ccl :clean t)' | ./dx86cl64
 echo '(rebuild-ccl :clean t)' | ./dx86cl64
 })

 <p>Create an executable script like the following.  You might want to call it
 ``@('ccl')'' and put it into a directory on your path.  Be sure to change the
 name (shown as ``2017-12-07-6be8298fe5'' above) to match the name change
 already made above.</p>

 @({
 #!/bin/sh

 export CCL_DEFAULT_DIRECTORY=/projects/acl2/lisps/ccl/2017-12-07-6be8298fe5/ccl
 ${CCL_DEFAULT_DIRECTORY}/scripts/ccl64 "$@"
 })

 <p>Now ensure that your script is executable, e.g.:</p>

 @({
 chmod +x my-script
 })

 <p>You're done!  (Note however that certification of @(see books) that use
 @(see Quicklisp) may require @('openssl') to be installed if it is not already
 on your system.)</p>")
other
(defxdoc cdaaar
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee caaar)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc cdaadr
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee caadr)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc cdaar
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee caar)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc cdadar
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee cadar)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc cdaddr
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee caddr)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc cdadr
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee cadr)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc cdar
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee car)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc cddaar
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee cdaar)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc cddadr
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee cdadr)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc cddar
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee cdar)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc cdddar
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee cddar)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc cddddr
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee cdddr)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc cdddr
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee cddr)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc cddr
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee cdr)"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(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>")
other
(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)")
other
(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>")
other
(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.  See @(see
 certify-book-debug) for some potential remedies for failures of
 @('certify-book').</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" 0 nil :acl2x t)
                                     ; ... writing or reading a .acl2x file
  (certify-book "my-arith" 0 t :useless-runes :write)
                                     ; ... write file to speed up future proofs
  (certify-book "my-arith" 0 t :useless-runes :read)
                                     ; ... read file to speed up future proofs

  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]
                :useless-runes          ; :write/:read/:read?/n/-n/nil
                                        ;   (-100 < n < 0 or 0 < n <= 100)
                                        ;   [default nil or from environment]
                :write-event-data       ; [default nil or from environment]
                )
 })

 <p>where @('book-name') is a book filename, @('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'),
 @('pcert'), @(':useless-runes'), and @(':write-event-data') can be affected by
 environment variables.  All of these arguments are described in detail below,
 except for @(':pcert'), @(':useless-runes'), and @(':write-event-data'): see
 @(see provisional-certification), @(see useless-runes), and @(see
 saving-event-data), respectively, for the effects of these three arguments and
 related environment variables, as we ignore those effects in the present
 topic.</p>

 <p>NOTE: If a given book includes some books (see @(see include-book)), then
 those included books need to be certified before the given book is certified.
 See @(see build::cert.pl) for a tool that certifies not only a given book but
 also all of the books that it includes, as well as all the books that those
 books include, and so on &mdash; all in the proper order, and with parallelism
 by using the @('-j') option.</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, or to
 avoid including undesired rules).  Alternatively, use @(tsee local) @(see
 events) to build your certification world, as these will be skipped when
 including the certified book.  But perhaps it's simplest just to get into the
 initial ACL2 @(see world) (e.g., with @(':ubt 1') or by just starting a new
 ACL2 run), then define the desired packages (directly with @(tsee defpkg) or
 by including books that define the packages), and finally invoke
 @('certify-book').</p>

 <p>The @('k') argument to @('certify-book') has default value @('0'), and it
 must be either a nonnegative integer or else the symbol @('?') 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>Otherwise, @('k') is @('?') (or any symbol whose @(tsee symbol-name) is
 @('"?"')).  In that case there is no check made on the certification world.
 This 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's filename.  Thus, a compiled file will appear atomically in its intended
 location.)  Finally, if @('compile-flg') is not supplied (or is @(':default'))
 then it is treated as @('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 t)') has been evaluated; see @(see
 set-guard-checking).  If you want to run with different guard-checking,
 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
 logical @(see world) (how far? &mdash; 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)); and
 (5) compiles the book if so directed (and then loads the object file in that
 case).</p>

 <p>@('Certify-book') is a macro that returns an @(see error-triple), where
 success is indicated by an error component of @('nil') and has the effect of
 extending the @(see world) with a corresponding @(tsee include-book) event.
 If you don't want the included book's @(see events) in your present @(see
 world), simply execute @(':')@(tsee u).</p>

 <p>Remark.  Step (3) above mentions rolling back the logical @(see world) to
 check for local incompatibilities.  This process is skipped if no @(see local)
 event is encountered.  Otherwise, the world is rolled back through the first
 local event past the boot-strap world &mdash; see @(see local-incompatibility)
 &mdash; before the book is included.  Note that if that first local event is
 in the certification world, then all commands from that event onward will be
 rolled back.  See @(see fast-cert) for a way to skip entirely this process of
 roll-back and check, regardless of local events, but with a risk to soundness.
 End of 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's
 filename.  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 this 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>")
other
(defxdoc certify-book-debug
  :parents (certify-book books-reference)
  :short "Some possible ways to work around @(tsee certify-book) failures"
  :long "<p>This topic provides some ideas for how to deal with @(tsee
 certify-book) failures.  Ideally, this topic will continue to grow over
 time.</p>

 <p>Stack overflows may show up as follows.</p>

 @({
 ***********************************************
 ************ ABORTING from raw Lisp ***********
 ********** (see :DOC raw-lisp-error) **********
 Error:  Stack overflow on value stack.
 ***********************************************
 })

 <p>When this occurs during book certification, it could be during an attempt
 to handle large objects, in particular by the @(see serialize) writer or by a
 @(see memoize)d version of the check for ``bad'' objects.  These two potential
 causes can be remedied by first evaluating the following forms,
 respectively.</p>

 @({
 (set-serialize-character-system nil state)
 (set-bad-lisp-consp-memoize nil)
 })

 <p>If the large object is in an event in the book under certification, then
 you may need to avoid printing it, as follows.</p>

 @({
 (set-inhibit-output-lst '(proof-tree event))
 })

 <p>Other failures of @('certify-book') may have error messages that point to
 the problem.  When that is not the case, it would be good to explain possible
 workarounds in this topic!</p>")
other
(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 filename, @('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>")
other
(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>")
other
(defxdoc char
  :parents (strings 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)")
other
(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>")
other
(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') states that its argument is a
 character.</p>

 <p>@('Char-downcase') is a Common Lisp function.  See any Common Lisp
 documentation for more information.  Note that the value returned may depend
 on the host Lisp; see @(see soundness), specifically Example 1 in the Section,
 &ldquo;Examples of divergence among Lisp implementations&rdquo;.</p>

 @(def char-downcase)")
other
(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') states that its arguments are both
 @(see characters).</p>

 <p>@('Char-equal') is a Common Lisp function.  See any Common Lisp
 documentation for more information.  Note that the value returned may depend
 on the host Lisp; see @(see soundness), specifically Example 1 in the Section,
 &ldquo;Examples of divergence among Lisp implementations&rdquo;.</p>

 @(def char-equal)")
other
(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') states that its argument is a
 character.</p>

 <p>@('Char-upcase') is a Common Lisp function.  See any Common Lisp
 documentation for more information.  Note that the value returned may depend
 on the host Lisp; see @(see soundness), specifically Example 1 in the Section,
 &ldquo;Examples of divergence among Lisp implementations&rdquo;.</p>

 @(def char-upcase)")
other
(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<)")
other
(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<=)")
other
(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>)")
other
(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>=)")
other
(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)")
other
(defxdoc 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-acl2.el') (from a suitable directory;
 see @(see emacs)) 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>")
other
(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)")
other
(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.
 Note that ACL2 supports characters with ASCII codes between 0 and 255.  See
 also @(see code-char) and @(see char-code).</p>")
other
(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 ISO-8859-1, 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>")
other
(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>")
other
(defxdoc checkpoint-summary-limit
  :parents (summary 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 !>
 })")
other
(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>")
other
(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>")
other
(defxdoc clause
  :parents (miscellaneous)
  :short "A representation of prover goals"
  :long "<p>In ACL2, a <i>clause</i> is a list of @(see term)s, and the meaning
 of a clause is the ACL2 disjunction of those terms where a term @('p') is
 considered ``false'' if ``@('p') = @('nil')'' and is true otherwise.  The
 elements of a clause are called ``literals,'' even though they are just terms.
 For example the goal @('(IMPLIES (AND p q) r)') is internally represented as
 the clause @('((NOT p) (NOT q) r)').  The literals of that clause are the
 terms @('(NOT p)'), @('(NOT q)'), and @('r').</p>

 <p>The ACL2 prover acts on clauses: a goal is represented as a clause, and
 each of the resulting subgoals is represented as a clause.  Thus, the terms
 (literals) in a clause are all translated (see @(see term)).</p>

 <p>To be precise, suppose that @('(L1 .. Lk M)') is a clause containing at
 least two literals.  ACL2 proof output displays that clause as an implication;
 this is called &ldquo;prettyifying a clause&rdquo;.  Below, @('~Li') denotes
 the <i>negation</i> of @('Li') in the following sense: if @('Li') is of the
 form @('(NOT P)') then @('~Li') designates @('P'), and otherwise @('~Li')
 designates @('(NOT Li)').</p>

 <blockquote>
 <p><b>Prettyifying a clause with at least two literals</b></p>
 @({
 (L1 .. Lk M)
 })
 <p>transforms it to the term</p>
 @({
 (IMPLIES (AND ~L1 ~L2 ... ~Lk)
          M).
 })
 </blockquote>

 <p>Of course, the disjunction represented by the clause is propositionally
 equivalent to the resulting call of @('IMPLIES').</p>

 <p>It is sometimes helpful to understand that ACL2's proof processes all
 operate on clauses.  In particular, proof output &mdash; obtained when @(see
 gag-mode) is turned off or when using @(':')@(tsee pso) or related utilities
 &mdash; may include a parenthetical remark as follows.  <b>WARNING</b>: This
 parenthetical remark is printed only by the main simplifier, not by the
 preprocessor (see @(see simple)).</p>

 @({
 This simplifies (dropping false conclusion; see :DOC clause), using ....
 })

 <p>What this remark signifies is that the last literal of the clause is false
 in at least one subgoal, and therefore does not appear in it (even in
 rewritten form).  Let's see how that works with the following example.</p>

 @({
 (defstub foo (x) t)
 (defaxiom foo-consp (implies (consp x) (foo x)))
 (set-gag-mode nil)
 (thm (implies (and (consp x) (natp (car x))) (not (foo x))))
 })

 <p>The proof attempt starts as follows.</p>

 @({
 ACL2 !>(thm (implies (and (consp x) (natp (car x))) (not (foo x))))

 By the simple :definition NATP we reduce the conjecture to

 Goal'
 (IMPLIES (AND (CONSP X)
               (INTEGERP (CAR X))
               (<= 0 (CAR X)))
          (NOT (FOO X))).

 This simplifies (dropping false conclusion; see :DOC clause), using
 the :rewrite rule FOO-CONSP, to

 Goal''
 (IMPLIES (AND (CONSP X) (INTEGERP (CAR X)))
          (< (CAR X) 0)).
 })

 <p>The change from @('Goal'') to @('Goal''') may be jarring because the
 &ldquo;conclusion&rdquo; &mdash; the second argument of the displayed
 @('IMPLIES') call &mdash; has changed drastically.  Let's analyze this change
 from the perspective of the goals printed; then we'll look at it from the
 perspective of clauses.</p>

 <p>A moment's reflection shows that because of the rule @('FOO-CONSP'),
 @('Goal'') is equivalent to</p>

 @({
 (IMPLIES (AND (CONSP X)
               (INTEGERP (CAR X))
               (<= 0 (CAR X)))
          NIL).
 })

 <p>And a little more reflection shows that the term above is propositionally
 equivalent to @('Goal''') above.</p>

 <p>But this may make more sense if we consider the clauses on which the prover
 operated.  Here are the clauses for @('Goal'') and @('Goal'''); the
 corresponding @('IMPLIES') terms displayed above are obtained by prettyifying
 the respective clauses (in the sense of &ldquo;prettyifying&rdquo; discussed
 above).</p>

 @({
 Goal'
 ((NOT (CONSP X))
  (NOT (INTEGERP (CAR X)))
  (< (CAR X) '0)
  (NOT (FOO X)))

 Goal''
 ((NOT (CONSP X))
  (NOT (INTEGERP (CAR X)))
  (< (CAR X) '0))
 })

 <p>For each of these clauses, the third literal, @('(< (CAR X) '0)'), is just
 the negation of the (untranslated) @(see term), @('(<= 0 (CAR X))'), shown in
 the prover output.</p>

 <p>Recall that a clause represents the disjunction of its literals.  Since the
 last literal of @('Goal''), @('(NOT (FOO X))'), rewrote to @('NIL') using the
 rule @('FOO-CONSP'), it was dropped when creating @('Goal'''): after all,
 @('(OR P NIL)') is propositionally equivalent to @('P').  So in @('Goal''')
 the last literal is @('(< (CAR X) '0)').  Therefore, the conclusion of each
 @('IMPLIES') term obtained by prettyifying the clause has changed from
 @('(NOT (FOO X))') to @('(< (CAR X) '0)').</p>

 <p>Finally, note that although &ldquo;dropping false conclusion&rdquo;
 signifies that the conclusion was dropped in at least one subgoal, if however
 there are at least two subgoals then it might not be dropped in all of them.
 Consider the following variant of the earlier example.</p>

 @({
 (defstub foo (x) t)
 (defaxiom foo-consp (implies (consp x) (foo x)))
 (set-gag-mode nil)
 (defstub bar (x) t)
 ; The proof fails for the following event (not important here).
 (thm (implies (and (or (bar x) (consp x)) (natp (car x)))
               (not (foo x)))
      :otf-flg t)
 })

 <p>The output includes the following.</p>

 @({
 Goal'
 (IMPLIES (AND (OR (BAR X) (CONSP X))
               (INTEGERP (CAR X))
               (<= 0 (CAR X)))
          (NOT (FOO X))).

 This simplifies (dropping false conclusion; see :DOC clause), using
 the :rewrite rule FOO-CONSP, to the following two conjectures.

 Subgoal 2
 (IMPLIES (AND (BAR X)
               (INTEGERP (CAR X))
               (<= 0 (CAR X)))
          (NOT (FOO X))).

 [[.. output elided ..]]

 Subgoal 1
 (IMPLIES (AND (CONSP X) (INTEGERP (CAR X)))
          (< (CAR X) 0)).
 })

 <p>We see that the conclusion was false, hence dropped, in Subgoal 1, but
 remained in Subgoal 2.</p>")
other
(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 @(see
 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 (and if @(':OR') @(see hints)
 are used, they may also contain symbols of the form @('Dn') where @('n') is a
 natural number, e.g., @('D23').)</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>")
other
(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), @(see df), 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 @(see clause): 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 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.  In most ways [3] and [3+] are treated similarly; see @(see
 make-summary-data) for a discussion of the form of @('d') in [3+] and, more
 generally, for how [3+] differs from [3] by enhancing the @(see summary).</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))

  [3+] ((CL-PROC cl hint st_1 ... st_k) => (mv erp cl-list st_i1 ... st_in d))
 })

 <p>We call @('cl-list') the <i>clauses-result</i>.  In [3] and [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 cases [3] and
 [3+], @('<CL-LIST>') is the result of wrapping the function
 @('clauses-result') around a call of @('CL-PROC'):</p>

 @({
  (clauses-result (CL-PROC CL HINT ...))
 })

 <p>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] and [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] or [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
 cases [3] and [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>

 ")
other
(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)")
other
(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)")
other
(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)")
other
(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>")
other
(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>")
other
(defxdoc coerce
  :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>")
other
(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>")
other
(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.
 })")
other
(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>")
other
(defxdoc comment
  :parents (hide acl2-built-ins)
  :short "Variant of @(tsee prog2$) to help debug evaluation failures during
 proofs"
  :long "<p>Semantically, @('(comment x y)') equals @('y'); the value of @('x')
 is ignored.  Thus @('comment') is much like @(tsee prog2$).  However, when you
 see a call of @('comment') in ACL2 proof output, it will likely be under a
 call of @(tsee hide), with information that may be helpful in understanding
 why the call of @('hide') was inserted.  Below we illustrate the various ways
 in which ACL2 may replace a term @('tm') by @('(hide (comment "..."
 tm))').  (On occasion you will simply see @('(hide tm)'); such cases are not
 discussed here.)</p>

 <p>Also see @(see hide) for further discussion of how to avoid such proof
 failures, and for how to keep the prover from inserting a @('comment') call
 under a call of @(tsee hide).</p>

 <h3>Evaluation during rewriting</h3>

 <p>Forms:</p>

 @({
 (HIDE (COMMENT "Failed attempt to call constrained function <fn>" <term>))
 (HIDE (COMMENT "Failed attempt to call non-executable function <fn>" <term>))
 })

 <p>Consider the following example.</p>

 @({
 (defstub f (x) t)
 (defun g (x) (cons (f x) x))
 (defund h (x) (cons x (cdr (g x))))
 (thm (equal (h 3) '(3 . 3)))
 })

 <p>Note that the @(see definition) of @('h') is disabled, but its @(see
 executable-counterpart) is not.  The proof attempt fails for the @(tsee thm)
 call, indicating the checkpoint shown below.</p>

 @({
 *** Key checkpoint at the top level: ***

 Goal'
 (EQUAL
  (HIDE
    (COMMENT "Failed attempt to call constrained function F;
 see :DOC comment"
             (H 3)))
  '(3 . 3))
 })

 <p>The first argument of @('equal') is logically just @('(h 3)').  But the
 @('comment') and @('hide') wrappers are telling us that evaluation of @('(h
 3)') failed because it led to a call of the constrained function @('f').  It
 is easy to see why in this case, by looking at the definitions, where @('h')
 calls @('g'), which calls @('f').  But more complicated such failures may be
 difficult to understand without such information.  In very complicated cases,
 one might even want to use the Lisp debugger after designating a @(tsee
 break$) call using @(tsee trace$), like this (here, shown using host Lisp
 CCL).</p>

 @({
 ACL2 !>(trace$ (f :entry (break$)))
  ((F :ENTRY (BREAK$)))
 ACL2 !>(thm (equal (h 3) '(3 . 3)))

 > Break: Break
 > While executing: BREAK$, in process listener(1).
 > Type :GO to continue, :POP to abort, :R for a list of available restarts.
 > If continued: Return from BREAK.
 > Type :? for other options.
 1 > :b ; user input to get backtrace
  (262932A0) : 0 (BREAK$) 157
  (262932F0) : 1 (F 3) 141
  (26293338) : 2 (FUNCALL #'#<(:INTERNAL ACL2_*1*_ACL2::G ACL2_*1*_ACL2::G)> 3) 37
  (26293350) : 3 (FUNCALL #'#<(:INTERNAL ACL2_*1*_ACL2::H ACL2_*1*_ACL2::H)> 3) 37
  (26293368) : 4 (RAW-EV-FNCALL H (3) NIL NIL [[.. output elided ..]]
 })

 <p>This output from Lisp is quite low-level, but reading from the bottom up
 provides the following sequence of events.</p>

 <ul>

 <li>4. Call @('h') with argument list @('(3)').</li>

 <li>3. Call the @(see executable-counterpart) of @('h').</li>

 <li>2. Call the @(see executable-counterpart) of @('g').</li>

 <li>1. Attempt to call the constrained function, @('f').</li>

 </ul>

 <p>An easy way to avoid this proof failure is to avoid execution of calls of
 @('h') and @('g'), as follows.</p>

 @({
 (thm (equal (h 3) '(3 . 3))
      :hints (("Goal" :in-theory (disable (:e g) (:e h)))))
 })

 <p>(It actually suffices to disable only @('(:e h)'), but the workings of the
 ACL2 rewriter are out of scope here.)</p>

 <p>If the offending function (here, @('f')) is introduced as @(see
 non-executable) rather than constrained, in particular if that function is
 defined using @(tsee defun-nx) or @(tsee defund-nx), then in the first
 argument of comment you will see ``non-executable'' instead of
 ``constrained''.</p>

 <h3>Evaluation during substitution</h3>

 <p>Form:</p>

 @({
 (HIDE
  (COMMENT
   "Failed attempt (during substitution) to call constrained function <fn>;
 see :DOC comment"
   <term>))
 })

 <p>Consider how ACL2 approaches the proof of the non-theorem below.</p>

 @({
 (defstub foo (x) t)
 (defund bar (x) (foo x))
 (thm (implies (equal x 3) (equal (bar x) yyy)))
 })

 <p>The prover attacks the @(tsee thm) event by substituting the constant
 @(''3') for @('x'), which results in an attempt to evaluate @('(bar 3)').
 This evaluation fails because @('bar') calls the undefined function @('foo').
 The checkpoint is as follows.</p>

 @({
 (EQUAL
  (HIDE
   (COMMENT
      "Failed attempt (during substitution) to call constrained function FOO;
 see :DOC comment"
      (BAR 3)))
  YYY)
 })

 <h3>Failure to expand using a rule</h3>

 <p>Form:</p>

 @({
 (HIDE (COMMENT "Unable to expand using the rule <name>;
 see :DOC comment"
                <term>))
 })

 <p>Consider how ACL2 approaches the proof for the second event below.</p>

 @({
 (defthm nth-open (implies (and (consp x) (posp n))
                           (equal (nth n x) (nth (1- n) (cdr x))))
   :rule-classes ((:definition :controller-alist ((nth t t)) :install-body t)))
 (thm (equal (nth i y) zzz)
      :hints (("Goal" :expand (nth i y) :do-not-induct t)))
 })

 <p>The checkpoint is as follows.  What happened is that the rule @('nth-open')
 had a hypothesis that was false when an attempt was made to apply it to the
 term @('(nth i y)').</p>

 @({
 (IMPLIES
  (NOT (CONSP Y))
  (EQUAL
   (HIDE (COMMENT "Unable to expand using the rule NTH-OPEN;
 see :DOC comment"
                  (NTH I Y)))
   ZZZ))
 })

 <h3>Failure due to disabled or missing warrants</h3>

 <p>Forms:</p>

 @({
 (HIDE (COMMENT "Call failed because the rule apply$-<fn> is disabled;
 see :DOC comment"
       <term>))
 (HIDE (COMMENT "Call failed because the warrant for <fn> is not known to be true;
 see :DOC comment"
       <term>))
 })

 <p>The first of these forms may appear when an attempt to evaluate a call of
 @(tsee apply$) fails because a necessary @(see warrant) is disable)d.  The
 second form may appear when the warrant is not known to be true in the present
 context, either because it is known to be false or because it cannot be
 assumed true because forcing is @(see disable)d.  In the following example,
 the attempt to simplify the call of @('apply$') in the theorem ultimately
 leads to an attempt to evaluate a call of @(tsee ev$), which ultimately fails
 because it leads to a call to evaluate @('(apply$ 'bar '(3))') @('bar').  That
 call causes an error because the warrant is unavailable since the rule
 @('apply$-bar') is disabled, hence cannot rewrite a term @('(apply$ 'bar
 args)') to @('(bar (car args))').</p>

 @({
 (include-book "projects/apply/top" :dir :system)
 (defun$ bar (x) x)
 (thm (implies (warrant bar)
               (equal (apply$ '(lambda (y) (bar y)) '(3)) 3))
      :hints (("Goal" :in-theory (disable apply$-bar ev$))))
 })

 <p>The checkpoint in the proof for the @('thm') just above is as follows.</p>

 @({
 (IMPLIES
  (APPLY$-WARRANT-BAR)
  (EQUAL
   (HIDE
    (COMMENT
       "Call failed because the rule APPLY$-BAR is disabled;
 see :DOC comment"
       (EV$ '(BAR Y) '((Y . 3)))))
   3))
 })

 <p>Similarly, if we instead submit the following event, we see the other such
 message, in this case about a false warrant.</p>

 @({
 (thm (implies (not (warrant bar))
               (equal (apply$ '(lambda (y) (bar y)) '(3)) 3))
      :hints (("Goal" :in-theory (disable ev$))))
 })

 <p>Here is the resulting checkpoint.</p>

 @({
 (IMPLIES
  (NOT (APPLY$-WARRANT-BAR))
  (EQUAL
   (HIDE
    (COMMENT
     "Call failed because the warrant for BAR is not known to be true;
 see :DOC comment"
     (EV$ '(BAR Y) '((Y . 3)))))
   3))
 })

 <p>Our final example illustrates a failure due to forcing being disabled.  The
 use of @(tsee loop$) in the definition of @('bar') expands to create a call of
 @(tsee ev$), which cannot be simplified during the proof of the @(tsee thm)
 below because the necessary warrant hypothesis is missing and cannot be
 forced, since forcing is disabled (see also @(see disable-forcing)).</p>

 @({
 (defun$ hello (x)
    (declare (xargs :guard t))
    (list 'hi x))

 (defun bar (lst)
    (declare (xargs :guard (true-listp lst)))
    (loop$ for name in lst collect (hello name))))

 (thm (equal (bar '(john))
             '((hi john)))
      :hints (("Goal" :in-theory (disable (:e force)))))
 })

 <p>Here is the resulting checkpoint.</p>

 @({
 (EQUAL
  (HIDE
   (COMMENT
    "Call failed because the warrant for HELLO is not known to be true;
 see :DOC comment"
    (EV$ '(RETURN-LAST 'PROGN
                       '(LAMBDA$ (LOOP$-IVAR)
                          (LET ((NAME LOOP$-IVAR))
                            (DECLARE (IGNORABLE NAME))
                            (HELLO NAME)))
                       ((LAMBDA (NAME) (HELLO NAME))
                        LOOP$-IVAR))
         '((LOOP$-IVAR . JOHN)))))
  '(HI JOHN))
 })")
other
(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>")
other
(defxdoc community-books
  :parents (books)
  :short "Libraries of ACL2 @(see books) developed by the ACL2 community."
  :long "<p>This topic discusses ACL2 @(see books), which are files of ACL2
 @(see events) like definitions and theorems.  See also @(see community).</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>Most installations of ACL2 contain a copy of the Community Books.  See
 @(see installation).</p>

 <p>Users are encouraged to contribute their own books.  See
 @(see how-to-contribute).</p>

 <p>See @(see community) for more ways to become involved with the ACL2
 community.</p>")
other
(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)
  (progn!
   :state-global-bindings
   ((acl2::temp-touchable-vars t acl2::set-temp-touchable-vars))
   (f-put-global 'acl2::logic-fns-with-raw-code
                 (cons 'my-fn (@ acl2::logic-fns-with-raw-code))
                 state))
 })")
other
(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>")
other
(defxdoc compare-objects
  :parents (debugging)
  :short "show differences between two ACL2 objects"
  :long "<p>In theorem prover output it can sometimes be difficult to
  see where two Lisp objects differ.  (Emacs' compare-windows can often help.)
  This function is an attempt to help while remaining entirely in ACL2.</p>

  @({
  General Form:
  (compare-objects x y)
  })

  <p>where @('x') and @('y') are two (almost) arbitrary objects but which must
  both be @('cons') trees for the comparison to be non-trivial.  The output
  (described below) might be confusing if either object contains keywords of
  the form @(':<|s...|>'), where the ellipsis is the decimal representation of a
  natural number.  For example, the output would be confusing if @('x') or
  @('y') contained @(':|<s1>|') because @('compare-objects') inserts tokens
  like that to mark differences.</p>

  <p>@('Compare-objects') walks through both objects to detect where
  corresponding substructures first differ.  It replaces differences by the
  keyword symbols @(':|<s1>|'), @(':|<s2>|'), @(':|<s3>|'), ..., which we call
  ``placeholders.''  It then assembles a ``legend'' that displays triplets of
  the form @('(si xi yi)') where @('si') is a placeholder marking a position in
  the common superstructure of both @('x') and @('y') and @('xi') and @('yi')
  are the substructures of @('x') and @('y'), respectively, at that position
  that differ.  @('Compare-objects') returns a list consisting of the ``common
  object'' showing the shared superstructure and the legend.</p>

  <p>For example,</p>

  @({
  ACL2 !>(compare-objects '(a b c) '(a b . c))
  ((:OBJ (A B . :|<s1>|))
   (:LEGEND ((:|<s1>| (C) C))))

  ACL2 !>(compare-objects '(f x y (g x '(a b c)))
                          '(f y x (g x '(a b c . d))))
  ((:OBJ (F :|<s1>|
            :|<s2>| (G X '(A B C . :|<s3>|))))
   (:LEGEND ((:|<s1>| X Y)
             (:|<s2>| Y X)
             (:|<s3>| NIL D))))
  })

  <p>By the way, the @('brr') command @(':')@(tsee explain-near-miss) sometimes
  calls @('compare-objects') to show the differences between two unequal quoted
  constants involved in a mismatch.  When @(':explain-near-miss') prettyprints
  the output of @('compare-object') it does so with an @(tsee evisc-tuple) that
  simplifies the placeholders.  @(':Explain-near-miss') would display the
  second example above as</p>

  @({
  ((:OBJ '(F <s1> <s2> (G X '(A B C . <s3>))))
   (:LEGEND ((<s1> X Y) (<s2> Y X) (<s3> NIL D)))).
  })

  <p>@('Compare-objects') might be especially helpful when looking at big
  @('lambda') objects as produced by translating and rewriting @(tsee loop$)
  expressions.  For example, below we use @('compare-objects') to discover
  where two large @('DO$') terms differ.</p>

  @({
  ACL2 !>(compare-objects
  '(DO$   ; First term
   '(LAMBDA (ALIST)
            (ACL2-COUNT (CDR (ASSOC-EQ-SAFE 'LST ALIST))))
   (CONS (CONS 'LST LST0) '((ANS . 0)))
   '(LAMBDA (ALIST)
            (IF (ENDP (CDR (ASSOC-EQ-SAFE 'LST ALIST)))
                (CONS ':RETURN
                      (CONS (CDR (ASSOC-EQ-SAFE 'ANS ALIST))
                            (CONS (CONS (CONS 'LST
                                              (CDR (ASSOC-EQ-SAFE 'LST ALIST)))
                                        (CONS (CONS 'ANS
                                                    (CDR (ASSOC-EQ-SAFE 'ANS ALIST)))
                                              'NIL))
                                  'NIL)))
                (CONS
                 'NIL
                 (CONS
                  'NIL
                  (CONS (CONS (CONS 'LST
                                    (CDR (CDR (ASSOC-EQ-SAFE 'LST ALIST))))
                              (CONS (CONS 'ANS
                                          (BINARY-+ '1
                                                    (CDR (ASSOC-EQ-SAFE 'ANS ALIST))))
                                    'NIL))
                        'NIL)))))
   '(LAMBDA (ALIST)
            (CONS 'NIL
                  (CONS 'NIL
                        (CONS (CONS (CONS 'LST
                                          (CDR (ASSOC-EQ-SAFE 'LST ALIST)))
                                    (CONS (CONS 'ANS
                                                (CDR (ASSOC-EQ-SAFE 'ANS ALIST)))
                                          'NIL))
                              'NIL))))
   '(NIL)
   'NIL)
  '(DO$   ; Second term
   '(LAMBDA (ALIST)
            (ACL2-COUNT (CDR (ASSOC-EQ-SAFE 'LST ALIST))))
   (CONS (CONS 'LST LST0) '((ANS . 0)))
   '(LAMBDA (ALIST)
            (IF (ENDP (CDR (ASSOC-EQ-SAFE 'LST ALIST)))
                (CONS ':RETURN
                      (CONS (CDR (ASSOC-EQ-SAFE 'ANS ALIST))
                            (CONS (CONS (CONS 'LST
                                              (CDR (ASSOC-EQ-SAFE 'LST ALIST)))
                                        (CONS (CONS 'ANS
                                                    (CDR (ASSOC-EQ-SAFE 'ANS ALIST)))
                                              'NIL))
                                  'NIL)))
                (CONS
                 'NIL
                 (CONS
                  'NIL
                  (CONS (CONS (CONS 'LST
                                    (CDR (CDR (ASSOC-EQ-SAFE 'LST ALIST))))
                              (CONS (CONS 'ANS
                                          (BINARY-+ '1
                                                    (CDR (ASSOC-EQ 'ANS ALIST))))
                                    'NIL))
                        'NIL)))))
   '(LAMBDA (ALIST)
            (CONS 'NIL
                  (CONS 'NIL
                        (CONS (CONS (CONS 'LST
                                          (CDR (ASSOC-EQ-SAFE 'LST ALIST)))
                                    (CONS (CONS 'ANS
                                                (CDR (ASSOC-EQ-SAFE 'ANS ALIST)))
                                          'NIL))
                              'NIL))))
   '(NIL)
   'NIL))
 ((:OBJ
  (DO$
   '(LAMBDA (ALIST)
      (ACL2-COUNT (CDR (ASSOC-EQ-SAFE 'LST ALIST))))
   (CONS (CONS 'LST LST0) '((ANS . 0)))
   '(LAMBDA (ALIST)
     (IF
       (ENDP (CDR (ASSOC-EQ-SAFE 'LST ALIST)))
       (CONS ':RETURN
             (CONS (CDR (ASSOC-EQ-SAFE 'ANS ALIST))
                   (CONS (CONS (CONS 'LST
                                     (CDR (ASSOC-EQ-SAFE 'LST ALIST)))
                               (CONS (CONS 'ANS
                                           (CDR (ASSOC-EQ-SAFE 'ANS ALIST)))
                                     'NIL))
                         'NIL)))
      (CONS
         'NIL
         (CONS 'NIL
               (CONS (CONS (CONS 'LST
                                 (CDR (CDR (ASSOC-EQ-SAFE 'LST ALIST))))
                           (CONS (CONS 'ANS
                                       (BINARY-+ '1
                                                 (CDR (:|<s1>| 'ANS ALIST))))
                                 'NIL))
                     'NIL)))))
   '(LAMBDA (ALIST)
      (CONS 'NIL
            (CONS 'NIL
                  (CONS (CONS (CONS 'LST
                                    (CDR (ASSOC-EQ-SAFE 'LST ALIST)))
                              (CONS (CONS 'ANS
                                          (CDR (ASSOC-EQ-SAFE 'ANS ALIST)))
                                    'NIL))
                        'NIL))))
   '(NIL)
   'NIL))
  (:LEGEND ((:|<s1>| ASSOC-EQ-SAFE ASSOC-EQ))))
  })

  <p>@('Compare-objects') tells us that a position @(':|<s1>|') the first term
  calls @('ASSOC-EQ-SAFE') while the second one calls @('ASSOC-EQ').</p>")
other
(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>")
other
(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
 })")
other
(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)))
 })")
other
(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>")
other
(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>")
other
(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
 may 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 <see topic='@(url
 type-reasoning)'>type reasoning</see> 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>")
other
(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 can remove 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 and the header may appear anywhere
 (even more than once), 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>

 <p>We close with a remark concerning efficiency in the case that the
 @(':ORDER') specified by the given @(see array)'s @(see header) is @('<') or
 @('>') and the alist is properly ordered: header occurring only first, then
 ascending (for @(':ORDER <')) or descending (for @(':ORDER >')) order of
 indices, with no value in the alist equal to the @(':DEFAULT') specified by
 the header.  In particular, this can cut the time to run @('compress1') on an
 alist containing only the header by more than half.</p>

 @(def compress1)")
other
(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)")
other
(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 symbol, in which case it must be a function symbol
 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 a @(see clause) named by some
 @(tsee goal-spec), e.g., "Subgoal *1/2'''".  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.</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>")
other
(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)")
other
(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 ``cond
 clauses'', each of which is a list.  In ACL2, cond clauses must have length 1
 or 2.</p>

 @({
 ; Example 1.  The form
   (COND ((CONSP X) (FOO X Y))
         ((SYMBOLP X) (BAR X Y))
         (T (LIST X Y)))
 ; abbreviates the following.
   (IF (CONSP X)
       (FOO X Y)
       (IF (SYMBOLP X)
           (BAR X Y)
           (LIST X Y)))

 ; Example 2.  The form
   (COND ((CONSP X))
         ((SYMBOLP X) (BAR X Y)))
 ; abbreviates the following.
   (OR (CONSP X)
       (IF (SYMBOLP X) (BAR X Y) NIL))
 })

 <p>The results above were obtained by typing @(':trans1') followed by the form
 in the ACL2 loop, and then hitting @('<RETURN>').  See @(see trans1).  You can
 experiment in this way to see other such examples.</p>

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

 @(def cond)
 @(def cond-macro)")
other
(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 @(see 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.  See @(see geneqv) for a discussion of how generated equivalence
 relations are derived using congruence rules and how generated equivalence
 relations are represented.</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 @(see
 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>")
other
(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)")
other
(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>")
other
(defxdoc cons-count-bounded
  :parents (conses acl2-built-ins)
  :short "Count the number of conses (up to a limit)"
  :long "<p>The call @('(cons-count-bounded x)') returns 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.</p>")
other
(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)")
other
(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-with-hint 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 (in the logic; it has a slightly different
 definition in raw Lisp).</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.  The choice was made to define
 @('remove-equal') ``under the hood'' to call Common Lisp's function,
 @('remove'); but 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>")
other
(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 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>")
other
(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.")
other
(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>")
other
(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).  For help in dealing with failures to
 prove constraint obligations generated by the @(':functional-instance')
 hint (see @(see hints)), see @(tsee set-constraint-tracking).</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 list of 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))))))))
 })")
other
(defxdoc constraint-info
  :parents (system-utilities constraint)
  :short "Obtaining the @(see constraint) on a function symbol"
  :long "<p>See @(see constraint)s for relevant background.
 @('Constraint-info') is a rather technical system utility, and detailed
 documentation may be found in comments in the ACL2 source code, in particular
 in the definition of @('constraint-info').  Here we give only an overview of
 this utility.</p>

 <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 x origins)'), as
 follows.  When @('flg') is @('nil'), @('x') is a term and @('origins') is a
 single <i>origin token</i> such as @('(DEFUN FN)'), indicating the source of
 the constraint, @('x'), on @('fn').  When @('flg') is non-@('nil') it is a
 function name, and usually @('x') is a list of terms and @('origins') is an
 equally long list of corresponding origin tokens; but there is a special case
 if the constraints are unknown, as can be the case with use of @(tsee
 partial-encapsulate).</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 x1 origin1)
             (constraint-info 'f1 wrld)
             (list flg1 x1 origin1))
           'f2
           (mv-let (flg2 x2 origin2)
             (constraint-info 'f2 wrld)
             (list flg2 x2 origin2))
           'f3
           (mv-let (flg3 x3 origin3)
             (constraint-info 'f3 wrld)
             (list flg3 x3 origin3))
           'f4
           (mv-let (flg4 x4 origin4)
             (constraint-info 'f4 wrld)
             (list flg4 x4 origin4))))
 (RESULT F1
         (F1 ((EQUAL (F4 X) (F3 X))
              (EQUAL (F1 X) (F4 X)))
             ((DEFUN F4) (THEOREM F1-PROP)))
         F2
         (NIL (EQUAL (F2 X) (F1 X)) (DEFUN F2))
         F3
         (F1 ((EQUAL (F4 X) (F3 X))
              (EQUAL (F1 X) (F4 X)))
             ((DEFUN F4) (THEOREM F1-PROP)))
         F4
         (F1 ((EQUAL (F4 X) (F3 X))
              (EQUAL (F1 X) (F4 X)))
             ((DEFUN F4) (THEOREM F1-PROP))))
 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>")
other
(defxdoc constraint-tracking
  :parents (encapsulate)
  :short "Generate markers to indicate origins of constraints"
  :long "See @(tsee set-constraint-tracking).")
other
(defxdoc context-message-pair
  :parents (kestrel-utilities system-utilities-non-built-in)
  :short "A common ACL2 programming idiom: @(see error-triple)s without @(see
 state)"
  :long "<p><i>Context-message pairs</i> are of the form @('(mv erp val)'),
 where there are the following two cases: the first indicates a successful
 computation and the second indicates an error.</p>

 <ul>

 <li><b>Normal case</b>: @('erp') is @('nil') and @('val') is what we call the
 ``value'' of that context-message pair.</li>

 <li><b>Error case</b>: @('erp') is not @('nil').  @('Val') may be @('nil');
 otherwise @('val') is a message (see @(see msgp)) suitable for printing with
 @(tsee fmt) and related functions using the @('~@') directive, and @('erp') is
 a context suitable for error messages (see @(see ctx)).  A convention
 generally observed (for example, by ACL2 system function
 @('cmp-to-error-triple'), which converts a context-message pair to an @(see
 error-triple) that may be printed in the error case) is when @('erp') and
 @('val') are both non-@('nil'), then @('erp') is not @('t').</li>

 </ul>

 <p>To see how this works let us consider the ACL2 source function,
 @('translate-cmp'), whose input is a user-level (``untranslated'') term as
 input and returns a context-message pair.  In the non-error case, the value
 returned is the internal (``translated'') form of that input; see @(see term).
 The log below first shows a successful translation, returning multiple values
 @('(mv nil (binary-+ x '3))'), thus illustrating the ``Normal case'' above,
 where the first value returned (the error indicator) is @('nil') and the
 second is the value of the pair.  The second example in the log shows an error
 case returning a context and a message.  Don't worry about the various
 arguments of @('translate-cmp'); the examples are merely to illustrate
 programming with context-message pairs, not to explain @('translate-cmp')!</p>

 @({
 ACL2 !>(translate-cmp '(+ x 3)
                       t t t 'top (w state)
                       (default-state-vars state))
 (NIL (BINARY-+ X '3))
 ACL2 !>(translate-cmp '(quote 3 4)
                       t t t 'top (w state)
                       (default-state-vars state))
 (TOP ("The proper form of a quoted constant is (quote x), but ~
                      ~x0 is not of this form."
           (#0 QUOTE 3 4)))
 ACL2 !>
 })

 <p>The following macros are useful when programming with context-message
 pairs.</p>

 <ul>

 <li>@('(value-cmp x)'): same as @('(mv nil x)').  Example:
 @({
 ACL2 !>(value-cmp (* 3 4))
 (NIL 12)
 ACL2 !>
 })</li>

 <li>@('(er-cmp ctx str &rest args)'): Return @('(mv ctx msg)') where @('msg')
 is formed from @('str') and @('args').  Example:
 @({
 ACL2 !>(er-cmp 'example
                "I don't like 3-element lists like ~x0.~|"
                (make-list 3))
 (EXAMPLE ("I don't like 3-element lists like ~x0.~|" (#0 NIL NIL NIL)))
 ACL2 !>(mv-let (ctx msg)
          (er-cmp 'example
                  "I don't like 3-element lists like ~x0.~|"
                  (make-list 3))
          (fmx "Error in ~x0: ~@1" ctx msg))
 Error in EXAMPLE: I don't like 3-element lists like (NIL NIL NIL).
 (0 <state>)
 ACL2 !>
 })</li>

 <li>@('(er-let*-cmp alist body)'): Analogue of @(tsee er-let*) for
 context-message pairs.  So, it evaluates the bindings in @('alist') much as
 @(tsee let*)-bindings would be evaluated, but where each expression should
 return a context-message pair and so should @('body').  If any of those
 expression evaluations returns a pair with a non-nil first value, then that
 pair is returned.  Otherwise, @('body') &mdash; which should return a
 context-message pair &mdash; is evaluated with respect to the resulting
 bindings.  Examples (refer to previous examples that use @('translate-cmp')):

 @({
 ACL2 !>(er-let*-cmp ((x (value-cmp '(+ x 3)))
                      (val (translate-cmp x
                                          t t t 'top (w state)
                                          (default-state-vars state)))
                      (y (value-cmp (list :term val))))
                     (value-cmp (list :result y)))
 (NIL (:RESULT (:TERM (BINARY-+ X '3))))
 ACL2 !>(er-let*-cmp ((x (value-cmp '(quote 3 4)))
                      (val (translate-cmp x
                                          t t t 'top (w state)
                                          (default-state-vars state)))
                      (y (value-cmp (list :term val))))
                     (value-cmp (list :result y)))
 (TOP ("The proper form of a quoted constant is (quote x), but ~
                      ~x0 is not of this form."
           (#0 QUOTE 3 4)))
 ACL2 !>
 })</li>

 <li>@('(er-progn-cmp form1 ... formk)'): Each @('formi') should evaluate to a
 context-message pair.  If any of these evaluations produces a pair with a
 non-@('nil') first component (thus indicating an error), return that pair.
 Otherwise return the context-message pair produced by evaluating @('formk').
 Examples:

 @({
 ACL2 !>(er-progn-cmp (value-cmp (+ 2 8))
                      (er-cmp 'top "Ouch")
                      (value-cmp (* 3 4)))
 (TOP ("Ouch"))
 ACL2 !>(er-progn-cmp (value-cmp (+ 2 8))
                      (value-cmp (* 3 4)))
 (NIL 12)
 ACL2 !>
 })</li>

 </ul>")
other
(defxdoc copyright
  :parents (about-acl2)
  :short "ACL2 copyright, license, authorship"
  :long "<p>This topic provides information about copyright, license, and
 authorship 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) 2026, 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>")
other
(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>")
other
(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)")
other
(defxdoc count-keys
  :parents (stobj acl2-built-ins)
  :short "Count the number of keys in association list"
  :long "<p>@('(Count-keys al)') returns the number of distinct keys in an
 association list.</p>

 <p>@('Count-keys') has a guard of @('t').  This function is called in the body
 of function, @('<h>-count') where @('<h>') is a hash-table field of a @(see
 stobj).  See @(see defstobj).</p>

 @(def hons-remove-assoc)

 @(def count-keys)")
other
(defxdoc course-materials
  :parents (documentation)
  :short "Some ACL2 course materials"
  :long "<p>The links listed below will take you to materials for some courses
that involve ACL2.  This list is loosely maintained and incomplete, and is
given in no particular order.  We strongly encourage you to send email to <a
href='mailto:kaufmann@cs.utexas.edu'>Matt Kaufmann</a> and <a
href='mailto:moore@cs.utexas.edu'>J Strother Moore</a> if you have additional
such links to contribute; or if you are a contributor to the ACL2 @(see
community-books), please feel free to add them yourself.</p>

<ul>

<li>See @(see recursion-and-induction) for notes you can use to teach yourself
how to prove theorems about recursively defined functions using mathematical
induction.  That document started as notes for the course &ldquo;Recursion and
Induction&rdquo; in the Department of Computer Science of the University of
Texas at Austin.</li>

<li><a href='https://www.ccs.neu.edu/home/pete/teaching.html'>Courses
    taught by Pete Manolios</a>, which use
    the <see topic='@(url acl2-sedan)'>ACL2 Sedan
    (ACL2s)</see>,
    including <a href='https://www.ccs.neu.edu/home/pete/courses/Logic-and-Computation/2020-Spring/'>one
    taught at Northeastern in Spring 2020</a></li>

<li>The following two interfaces to ACL2 support the teaching of ACL2
to undergraduates:

  <ul>

  <li>The <see topic='@(url acl2-sedan)'>ACL2 Sedan (ACL2s)</see></li>

  <li><a href='http://dracula-lang.github.io/index.html'>DrACuLa</a></li>

  </ul></li>

<li>John Cowles, <a href='http://www.cs.uwyo.edu/~cowles/jvm-acl2/'>COSC5010:
Formalizing the JVM in ACL2</a>, Univ. of Wyoming</li>

<li>Links to some of Warren Hunt's courses, many of which use ACL2, may be found <a
href='http://www.cs.utexas.edu/users/hunt/class/index.html'>here</a>.</li>

<li>Links to some of J Moore's courses, many of which use ACL2, may be found <a
href='http://www.cs.utexas.edu/users/moore/classes/index.html'>here</a>.</li>

</ul>

")
other
(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)")
other
(defxdoc creating-executable
  :parents (installation-support)
  :short "Creating or obtaining an executable image"
  :long "<p>This topic may be avoided by following the @(see
  installation-instructions), which are intended to be
  self-contained.</p>

 <p>After obtaining the ACL2 sources, the next step is to produce an executable
 image.  Proceed according to one of the four sections below, and after reading
 that section, continue by reading the topic, see @(see using-acl2).</p>

 <ul>

 <li>Pre-built images</li>

 <li>Building an executable image on a Unix-like system</li>

 <li>Building an executable image on other than a Unix-like system</li>

 <li>Observations on building an executable image on a Windows system</li>

 </ul>

 <h3>Pre-built images</h3>

 <p>@(`(:raw (acl2-url-ref "distrib/images/Readme.html" "This website"))`)
 contains links to ACL2 executables and packages.  Each @('-md5sum') file was
 created using @('md5sum').  We may add additional links from time to time.</p>

 <p>See also @(see pre-built-binary-distributions).</p>

 <h3>Building an executable image on a Unix-like system</h3>

 <p>We assume you have obtained ACL2, described in
 @(see installation-instructions),
 but you have not obtained a pre-built image.  Change to the directory containing
 the ACL2 sources and execute the command</p>

 @({
 make LISP=<your_lisp>
 })

 <p>where @('<your_lisp>') is the command to run your local Common Lisp.
 By default, if no @('LISP=<your_lisp>') is specified, then @('LISP=ccl') is
 used, which presumably invokes CCL (see @(see obtaining-common-lisp)).</p>

 <p>This will create executable @('saved_acl2') in the current directory.</p>

 <p>The time taken to carry out this process depends on the host Lisp and the
 host processor but may well be under a minute.  The size of the resulting
 binary image is dependent on which Lisp was used, but it may be on the order
 of a couple hundred megabytes or so.</p>

 <p>This @('make') command works for the supported host Common Lisp
 implementations; see @(see obtaining-common-lisp), on systems we have
 tested.  If this @('make') command does not work for you, see the instructions
 below for &ldquo;Building an executable image on other than a Unix-like
 system&rdquo;.</p>

 <p>See @(see save-exec) for how to build an ACL2 executable from a state
 resulting from the running of specified @(see command)s.</p>

 <h3>Building an executable image on other than a Unix-like system</h3>

 <p>It may be best to use this option only if you are using a Common Lisp on
 which you cannot save an image (e.g., a trial version of a commercial
 lisp).</p>

 <p>Next we describe how to create a binary image containing ACL2 without using
 the `@('make')' utility.  If you cannot save an image, perhaps because you are
 using a trial version of your Common Lisp, then you may not be able to save an
 image.  In that case, see @(see running-acl2-without-executable).</p>

 <p>Your Common Lisp should be one of those listed in @(see
 obtaining-common-lisp).  Stand in the directory where you have downloaded
 ACL2.</p>

 <ol>

 <li>Remove file @('nsaved_acl2') if it exists.</li>

 <li>Start up Common Lisp and submit the following sequence of commands.

 @({
 (load "init.lisp")
 (in-package "ACL2")
 (compile-acl2) ; essentially a no-op if the Lisp is CCL or SBCL
 })

 The commands above may, depending on the host Lisp, compile the ACL2 sources
 and create compiled object files in the current directory.  (But they should
 be run even for Lisps that do not compile the ACL2 sources.)  Below, we assume
 that saved images have extension @('.core'); but this will depend on your host
 Lisp and operating system.</li>

 <li>Now exit your Common Lisp.  Make sure you are in the directory where you
 ran the commands displayed above.  Start your Common Lisp and run the
 following commands to <i>initialize</i> ACL2.

 @({
 (load "init.lisp")
 (in-package "ACL2")
 (save-acl2 (quote (initialize-acl2)) "saved_acl2")
 })

 This will load ACL2 source files (possibly compiled) into Lisp and then
 bootstrap ACL2 by reading and processing the source files, concluding by
 saving an image.  Exit Lisp now.  Subsequent steps will put the image in the
 right place.</li>

 <li>Remove @('osaved_acl2') if it exists.</li>

 <li><b>IF</b> @('saved_acl2') and @('saved_acl2.core') both exist <b>THEN</b>:
 <ul>
      <li>move @('saved_acl2.core') to @('osaved_acl2.core')</li>
      <li>move @('saved_acl2') to @('osaved_acl2')
          and edit @('osaved_acl2'), changing @('saved_acl2.core')
          (at end of line) to @('osaved_acl2.core')</li>
 </ul>
      <b>ELSE IF</b> @('saved_acl2') exists <b>THEN</b>:
 <ul>
      <li>move @('saved_acl2') to @('osaved_acl2')</li>
 </ul>
 </li>

 <li>Move @('nsaved_acl2') to @('saved_acl2') .</li>

 <li>Move @('nsaved_acl2.core') to @('saved_acl2.core') .</li>

 <li>Make sure @('saved_acl2') is executable.  For Windows
 this involves two mini-steps:

 <ul>

 <li>Remove the @('"$@"') from the @('saved_acl2') script (because Windows
 may not understand @('"$@"')).  Consequently, any arguments you pass to ACL2
 via the command line will be ignored.</li>

 <li>Rename @('saved_acl2') to @('saved_acl2.bat'), for
 example by executing the following command.
 @({
 rename saved_acl2 saved_acl2.bat
 })</li>

 </ul>
 </li>
 </ol>

 <h3>Observations on building an executable image on a Windows system</h3>

 <p>You may be able to avoid this section by downloading a pre-built binary
 distribution; see @(see pre-built-binary-distributions), and also see
 &ldquo;Pre-built images&rdquo; above.</p>

 <p>Otherwise, see @(see windows-installation) for information on installing
 ACL2 on Windows systems.</p>")
other
(defxdoc ctx
  :parents (errors)
  :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.  (See @(see
 ctxp) for the definition of a valid context.)</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>")
other
(defxdoc ctxp
  :parents (errors)
  :short "Recognizer for context objects for error messages"
  :long "<p>See @(see ctx) for relevant background.  The function @('ctxp')
  returns @('t') when @('ctx') is a valid context according to the definition
  below (also see @(see msgp)), else @('nil').</p>

 @(def ctxp)")
other
(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>")
other
(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>")
other
(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>")
other
(defxdoc cw
  :parents (io acl2-built-ins)
  :short "Print to the comment window"
  :long "<p>@('Cw') is a macro that expands to a function whose guard is
 @('t').  For a guarded variant of @('cw'), see @(see fmx-cw).  For variants of
 @('cw') that provide readable output (suffix @('"!"')) and are never
 inhibited (suffix @('"+"')), see @(see cw!), @(see cw+), and @(see cw!+).
 For corresponding functions see @(see fmt-to-comment-window), @(see
 fmt-to-comment-window!), @(see fmt-to-comment-window+), and @(see
 fmt-to-comment-window!+).</p>

 <p>Example:</p>

 @({
  (cw "The goal is ~x0 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 four 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: ~x0 and ~x1" ans1 ans2)
 })

 <p>prints in the same manner as:</p>

 @({
  (fmt "Answers: ~x0 and ~x1"
       (list (cons #\0 ans1) (cons #\1 ans2))
       *standard-co* state nil)
 })

 <p>And finally, output from @('cw') is suppressed if the @('COMMENT') type of
 output is suppressed; see @(see set-inhibit-output-lst).</p>

 <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>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))))
 })")
other
(defxdoc cw!
  :parents (cw io acl2-built-ins)
  :short "Print readably to the comment window"
  :long "<p>See @(see cw) for important background.</p>

 <p>This is nearly the same as @(tsee cw), but @('cw!') avoids
 inserting backslash (\) characters when forced to print past the right
 margin.  Use @('cw!') if you want to be able to read the forms back in.</p>")
other
(defxdoc cw+
  :parents (cw io acl2-built-ins)
  :short "Print uninhibited to the comment window"
  :long "<p>See @(see cw) for important background.</p>

 <p>This is nearly the same as @(tsee cw), but @('cw+') always produces output,
 even when the @('COMMENT') output type is inhibited (see @(see
 set-inhibit-output-lst)).</p>")
other
(defxdoc cw!+
  :parents (cw io acl2-built-ins)
  :short "Print readably and uninhibited to the comment window"
  :long "<p>See @(see cw) for important background.</p>

 <p>This is nearly the same as @(tsee cw), but @('cw+') always produces
 readable output (like @(tsee cw!)), even when the @('COMMENT') output type is
 inhibited (like @(tsee cw+)).</p>")
other
(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') or in the scope of @(tsee with-brr-data)), @('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 by default,
 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>'); this behavior can be changed by setting the
 @(':TERM') @(see evisc-tuple) (see @(see set-evisc-tuple)).  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>")
other
(defxdoc cw-print-base-radix
  :parents (io acl2-built-ins)
  :short "Print to the comment window in a given print-base"
  :long "<p>See @(tsee cw) for relevant background.  This variant of @('cw')
 requires specification of a print-base and, optionally, a print-radix (see
 @(see set-print-base), @(see set-print-radix), and @(see
 set-print-base-radix)).</p>

 <p>The following examples show that @('cw-print-base-radix') is just like
 @(tsee cw), except that there is a new argument in the first position that
 specifies the print-base and can, for that print-base, override the default
 print-radix.</p>

 @({
 ACL2 !>(cw-print-base-radix 16 "~x0~%" '(3 12 16 17))
 (#x3 #xC #x10 #x11)
 NIL
 ACL2 !>(cw-print-base-radix '(16 . t) "~x0~%" '(3 12 16 17))
 (#x3 #xC #x10 #x11)
 NIL
 ACL2 !>(cw-print-base-radix '(16 . nil) "~x0~%" '(3 12 16 17))
 (3 C 10 11)
 NIL
 ACL2 !>(cw-print-base-radix 10 "~x0~%" '(3 12 16 17))
 (3 12 16 17)
 NIL
 ACL2 !>(cw-print-base-radix '(10 . t) "~x0~%" '(3 12 16 17))
 (3. 12. 16. 17.)
 NIL
 ACL2 !>(cw-print-base-radix '(10 . nil) "~x0~%" '(3 12 16 17))
 (3 12 16 17)
 NIL
 ACL2 !>

 General Forms:

 (cw-print-base-radix print-base fmt-string arg1 arg2 ... argn)
 (cw-print-base-radix print-base/print-radix fmt-string arg1 arg2 ... argn)
 })

 <p>where all arguments of this macro are evaluated; @('print-base') is a legal
 print-base as recognized by @(tsee print-base-p); @('print-base/print-radix')
 is a cons whose car is a legal print-base; @('fmt-string') is a string
 suitable for passing to @(tsee fmt); and @('arg1') through @('argn') (where n
 is at most 9) are corresponding arguments for @('fmt-string').  Printing is
 done according to the specified print-base, which is the first argument in the
 first general form and is the car of the first argument in the second general
 form.  The print-radix value that is used for printing in the first general
 form is the print-radix as specified for @(tsee set-print-base-radix), while
 in the second general form, it is the cdr.</p>")
other
(defxdoc cw-print-base-radix!
  :parents (io acl2-built-ins)
  :short "Print to the comment window in a given print-base"
  :long "<p>This is nearly the same as @(tsee cw-print-base-radix), but
  @('cw-print-base-radix!') avoids inserting backslash (\) characters when
  forced to print past the right margin.  Use @('cw-print-base-radix!')  if you
  want to be able to read the forms back in.</p>")
other
(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>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 large subset of the first-order <b>applicative</b> part of Common
 Lisp.  (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.)  It
 does not support higher-order features of Common Lisp, like functional objects
 and <tt>apply</tt>.  It does not support Common Lisp primitives that have
 side-effects such as <tt>setq</tt>, <tt>setf</tt>, the Common Lisp Object
 System, etc.  However, ACL2 does provide some special features that can be
 used efficiently to do many of the same jobs as these omitted Common Lisp
 primitives.  The ACL2 system is largely implemented in the language it
 supports.</p>

 <p><see topic='@(url |An Example Common Lisp Function Definition|)'><img
 src='res/tours/walking.gif'></img></see></p>")
other
(defxdoc |Common Lisp as a Modeling Language|
  :parents (|Pages Written Especially for the Tours|)
  :short "Common Lisp as a Modeling Language"
  :long "<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>")
other
(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>")
other
(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 @(see 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>")
other
(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>")
other
(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
 @(See 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 use 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>")
other
(defxdoc debugging
  :parents (top)
  :short "Tools for debugging failed or slow proofs, or misbehaving
 functions.")
other
(defxdoc declare
  :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 in the following
 display (not including lambda objects, discussed later below, and not showing
 documentation strings here, which are essentially ignored by ACL2)):</p>

 <ul>
 <li>@('(DEFUN name args dcl ... dcl body)')</li>
 <li>@('(DEFMACRO name args 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>
 <li>@('(MACROLET ((name args dcl ... dcl body) ...))')</li>
 </ul>

 <p>Each of the cases above permits certain declarations, as follows.</p>

 <ul>

 <li>@('DEFUN'): @(`(cdr (assoc-eq 'defuns *acceptable-dcls-alist*))`)</li>
 <li>@('DEFMACRO'): @(`(cdr (assoc-eq 'defmacro *acceptable-dcls-alist*))`)</li>
 <li>@('LET'): @(`(cdr (assoc-eq 'let *acceptable-dcls-alist*))`)</li>
 <li>@('MV-LET'): @(`(cdr (assoc-eq 'mv-let *acceptable-dcls-alist*))`)</li>
 <li>@('FLET'): @(`(cdr (assoc-eq 'flet *acceptable-dcls-alist*))`)</li>
 <li>@('MACROLET'): @(`(cdr (assoc-eq 'macrolet *acceptable-dcls-alist*))`)</li>
 </ul>

 <p>Of course, declarations are permitted in macro calls to the extent that
 they are permitted in the macroexpansions.  For example, @('declare') forms
 generated by calls of @(tsee let*) and @(tsee case-match) may wind up in
 corresponding @(tsee let) forms in the macroexpansions, where they would be
 subject to the restrictions on @('declare') forms for @('let') shown just
 above.</p>

 <p>Also see @(see lambda) for discussion of lambda objects and their legal
 @('declare') forms.</p>

 <p>@('Declare') is defined in Common Lisp.  See any Common Lisp documentation
 for more information.</p>")
other
(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>")
other
(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>")
other
(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>Recall that 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 existing stobj, its
 ``foundation'', which is either <i>concrete</i> (introduced by @(tsee
 defstobj)) or <i>abstract</i> (introduced by @('defabsstobj')).</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 &mdash; where every data object is an
 atom or a @(tsee cons) of data objects &mdash; 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
 typically an array object whose fields correspond to those specified by the
 @(tsee defstobj) event.  (If there is a single stobj field that is an array or
 hash-table field, then that field is the entire stobj in raw Lisp; but we
 ignore that case below.)</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>

 <ol>

 <li>When @('foo') is executed on concrete data in the ACL2 loop,
 the guard check may be expensive because @('(good-stp st)') is expensive.</li>

 <li>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.</li>

 </ol>

 <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 ``foundational stobj'' introduced by an
 earlier @(tsee defstobj) or @('defabsstobj') 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 (as discussed
 above).</p>

 <p>Remark.  It is common to use ``a'' and ``c'' in a suffix to suggest
 ``abstract'' and ``concrete'', respectively.  The foundational stobj was, at
 one time, called the ``corresponding concrete stobj''.  That old terminology
 may still be appropriate in the common case that the foundational stobj is a
 concrete stobj (rather than another abstract stobj).  So below, a name like
 @('st$c0') suggests a foundational (``concrete'') stobj for an abstract stobj
 named @('st'), whose abstract stobj recognizer is @('st$ap'), and so on.  End
 of Remark.</p>

 <p>We can picture a sequence of updates to an abstract stobj and its
 foundational stobj.  Initially in this picture, @('st$a0') and @('st$c0') are
 an abstract stobj and its foundation (respectively).  Then an update, @('u1'),
 is applied with @(':LOGIC') and @(':EXEC') functions @('u$a1') and @('u$c1'),
 respectively.  The resulting abstract and foundational 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
  Foundation       st$c0  --> st$c1  --> st$c2  -->   ...
  (:exec)
 })

 <p>We conclude this introduction with some remarks about implementation.
 Consider an abstract stobj @('st') with corresponding foundation @('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 truly congruent: in particular, the stobj primitives introduced for
 @('st') may be applied to @('st'), but field updaters of @('st$c') may not.
 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/demos/defabsstobj-example-1.lisp')
 and @('books/demos/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.  There are other books
 @('books/dmeos/defabsstobj-example-*.lisp') that may be helpful to read; in
 particular, @('books/demos/defabsstobj-example-5.lisp') illustrates building
 an abstract stobj on top of another abstract stobj (as its so-called
 ``foundation'', as described below).</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 the 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 foundational stobj for st is st$c:

   :foundation 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 foundational stobj.  The function
 ; st$corr, which need not be executable (see :DOC defun-nx), takes two
 ; arguments, a foundational 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})))
 </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.  @(csee Guard)s
 are 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 foundational 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>Note that the @(':EXEC') version of an abstract @(see stobj) export must
 not include the abstract stobj name among its formals.</p>

 <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 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
 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 foundational
 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 foundational 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
    :foundation foundation
    :recognizer recognizer
    :creator creator
    :corr-fn corr-fn
    :corr-fn-exists corr-fn-exists
    :congruent-to congruent-to
    :non-executable non-executable
    :protect-default protect-default
    :attachable att
    :exports (e1 ... ek))
 })

 <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).  Each
 @('vali') must be a symbol.  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>@('Foundation') is the name of an existing stobj, which may have been
 introduced either with @(tsee defstobj) or with @('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 foundational stobj (which
 can be specified using the @(':FOUNDATION') keyword).</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
 @(':EXEC') function must be the creator for the foundational stobj (which can
 be specified using the @(':FOUNDATION') keyword).</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>@('Corr-fn-exists') is a Boolean with default @('nil'), which will
 generally serve well.  See @(see stobj-attachment-restrictions) for a
 discussion of this argument.</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
 foundational stobj (not merely congruent foundational 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>@('Non-executable') should either be @('nil') (the default) or @('t').
 When @('t'), a global stobj is not created for the given name; see @(see
 defstobj), Section &ldquo;Specifying Non-executable Stobjs&rdquo;, for
 details, as the meaning of @(':non-executable') is the same for
 @('defabsstobj') as it is for @('defstobj').</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>@('Attachable') should be @('nil') (the default) or @('t').  See @(see
 attach-stobj) for a discussion of this keyword.</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 keywords @(':CORR-FN') and @(':CORR-FN-EXISTS'), 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'), @(':GUARD-THM'), @(':PROTECT'), and
 @(':UPDATER'), and also @(':PRESERVED') if and only if the specified
 @(':EXEC') function returns the foundational stobj.  The default values for
 all of these keywords except @(':UPDATER') and @(':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').  If @(':UPDATER upd') is supplied and
 @('upd') is not @('nil'), then function exported by the function spec is a
 child stobj accessor whose corresponding updater is @('upd'); see the
 discussion of @(':UPDATER') in @(see nested-stobjs).</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 foundational 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>Additional restrictions include the following.</p>

 <ul>

 <li>All exported function names must be new (unless redefinition is on; see
 @(see ld-redefinition-action)), and there must be no duplicates among
 them.</li>

 <li>The foundational stobj name must be a formal parameter of the @(':EXEC')
 function of every function spec, except for the @(':CREATOR') function
 spec.</li>

 <li>The @(':LOGIC') and @(':EXEC') function for a function spec must agree on
 both the number of inputs and the number of outputs.</li>

 <li>The foundational stobj must not be a @(see declare)d stobj of the
 @(':LOGIC') function of any function spec.  (This restriction could perhaps be
 removed, but it is convenient for the implementation of the events generated
 by a call of @('defabsstobj').)</li>

 <li>The @(':PROTECT') keyword is something that you should ignore unless you
 get an error message about it, pertaining to modifying the foundational 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, in order to restore the
 required atomicity.  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/demos/defabsstobj-example-2.lisp').</li>

 </ul>

 <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
 foundational stobj at most once &mdash; i.e., modification of the foundational
 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 foundational 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/demos/defabsstobj-example-3.lisp') and
 @('books/demos/defabsstobj-example-4.lisp') provide related information.  Also
 see @(see set-absstobj-debug) for a potentially dangerous way to eliminate
 that inefficiency using argument @(':ignore').</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, to
 agree with non-memoizability of the foundational 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 foundational stobj.</p>")
other
(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>")
other
(defxdoc defattach
  :parents (events)
  :short "Execute constrained functions using corresponding attached functions"
  :long "
 @({
  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 in
 the list @(`*defattach-keys-extended*`).  More details are in the ``Syntax and
 Semantics'' section below.</p>

 <p>A related utility can cause a function call to be evaluated using an
 alternate, provably equal function.  See @(see memoize), option
 @(':INVOKE').</p>

 <p>This @(see documentation) topic is organized into the following
 sections:</p>

 <ul>

 <li>Introductory Example.</li>

 <li>Syntax and Semantics of Defattach.</li>

 <li>Three Primary Uses of Defattach.</li>

 <li>Miscellaneous Remarks, with discussion of possible user errors.</li>

 </ul>

 <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>

 <h3>Introductory Example.</h3>

 <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 !>
 })

 <h3>Syntax and Semantics of Defattach.</h3>

 <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 :kwd11 val11 ...)
             ...
             (fk gk :kwdk1 valk1 ...)
             :kwd1 val1 ...)
 })

 <p>where each indicated keyword-value pair is optional and each keyword is in
 the list @(`*defattach-keys-extended*`).  We distinguish between keywords
 within the @('(fi gi :kwdi1 vali1 ...)'), which we call <i>guard keywords</i>,
 and keywords at the top level, shown above as @(':kwd1 val1 ...'), which we
 call <i>top-level keywords</i>.</p>

 <ul>

 <li>The guard keywords are in the list @(`*defattach-keys*`).  The
 @(':')@(tsee hints), @(':')@(tsee instructions), and @(':')@(tsee otf-flg)
 keywords in @('(fi gi ...)') are used in the proofs of the guard proof
 obligation for the attachment of @('gi') to @('fi').  They have their usual
 values and meanings, as when used (for example) in @(tsee defthm) @(tsee
 events).  The value of each @(':attach') keyword is either @('t') or @('nil').
 We discuss the @(':attach') keyword later in this @(see documentation)
 topic.</li>

 <li>The top-level keywords @(':hints'), @(':instructions'), and @(':otf-flg')
 are used in the constraint proof obligations just as described above for the
 guard proof obligations.  When @(':attach') is used as a top-level keyword,
 its value serves as a default for entries @('(fi gi ...)') that do not specify
 @(':attach').  @(':Skip-checks') and @(':system-ok') are described below.</li>

 </ul>

 <p>No keyword may occur twice in the same context: that is, neither twice as a
 guard keyword in the same @('(fi gi ...)')  entry, nor twice as a top-level
 keyword.  Moreover, @(':instructions') may not occur in the same context with
 @(':hints') or @(':otf-flg').</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 (defined below) and hence the check for cycles in
 this relation (which is discussed below).  We do not make any logical claims
 when the value of @(':skip-checks') is non-@('nil'); indeed, a trust tag is
 then required (see @(see defttag)).  Note that the interaction of @(see
 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>The argument @(':system-ok t') allows attachment to system functions.
 Without this argument, the @('defattach') event will fail if any @('fi') is a
 built-in ACL2 function.  Rather than supplying this argument directly, it is
 recommended to use @(tsee defattach-system), which has the same syntax as
 @('defattach') with two exceptions: it adds @(':system-ok t') automatically,
 that is, @(':system-ok') is implicit; and it expands to a @(tsee local) call
 of @('defattach').  The latter is important so that the attachment does not
 affect system behavior outside a book containing the @('defattach') event.  Of
 course, if it is truly intended to affect such behavior, the argument
 @(':system-ok t') may be given directly to @('defattach'), without a
 surrounding use of @('local').</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 <i>extended immediate
 ancestor of</i> 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').  We also consider @('g') to be an extended
 immediate ancestor of @('f') if there are function symbols @('f'') and @('g'')
 that are introduced in the same events as @('f') and @('g'),
 respectively (such as the same @(tsee mutual-recursion) or the same @(tsee
 encapsulate) with non-empty signatures), such that @('g'') is an extended
 immediate ancestor of @('f'') in the sense above.  For a proposed
 @('defattach') event, we check that the graph defined by 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>

 <h3>Three Primary Uses of Defattach.</h3>

 <p>We anticipate three uses of @('defattach'):</p>

 <ol>

 <li>Constrained function execution</li>

 <li>Sound modification of the ACL2 system</li>

 <li>Program refinement</li>

 </ol>

 <p>We discuss these in turn.</p>

 <ol>

 <li>The example at the beginning of this @(see documentation) illustrates
 constrained function execution.</li>

 <li>ACL2 is written essentially in itself.  Thus, there is an opportunity to
 attach 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.  See @(see system-attachments).  To find all
 such examples, search the source code for the string `-builtin'.<br/>

 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.</li>

 <li>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.</li>

 </ol>

 <h3>Miscellaneous Remarks, with discussion of possible user errors.</h3>

 <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.  Another example is that a meta function or clause-processor
 function can call functions that have attachments, with a restriction that
 those attached functions must not also be ancestral in a corresponding
 evaluator.  See @(see evaluator-restrictions) for a discussion of that
 restriction, and see @(see transparent-functions) for a device that can relax
 the restriction (while imposing additional requirements on attachments).</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>(Of interest only to users of @(tsee apply$).)  Special handling is applied
 when attempting to attach to a so-called <i>warrant</i>, which is produced by
 an application of @(tsee defwarrant) (or @(tsee defun$)).  In that case it is
 legal to attach the function @('true-apply$-warrant') to the warrant, without
 any proof obligation.  This attachment is actually performed automatically by
 @('defwarrant'), so users (even users of @('apply$')) need not deal
 explicitly with such attachments.  However, these attachments make warrants
 executable in the loop; for example, after @('(defwarrant foo)'), @('(warrant
 foo)') will evaluate to @('t') in the loop.</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>The form @('(all-attachments (w state))') evaluates to the list of all
 attachments except in two cases: @(see warrant)s, and attachments introduced
 with a non-@('nil') value of @(':skip-checks').  To obtain the attachment to a
 function symbol @('FN'), without the above restrictions 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>The advanced feature, @(tsee with-global-stobj), imposes certain
 restrictions on a @('defattach') event.  You can probably ignore this point
 unless you get an error pertaining to @('with-global-stobj').  For relevant
 documentation see @(see with-global-stobj), specifically the section on
 ``Constrained Functions and Defattach''.</p>

 <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>")
other
(defxdoc defattach-system
  :parents (defattach)
  :short "Attach to built-in, system-level, constrained functions"
  :long "<p>For background on attachments, see @(see defattach).  The macro
 @('defattach-system') is a convenient way to attach to built-in functions.
 The event @('(defattach f g)') will fail if @('f') is built into ACL2.  This
 failure can be overcome by specifying top-level keyword argument @(':system-ok
 t'), for example: @('(defattach (f g) :system-ok t)').  However, rather than
 supplying this argument directly, it is recommended to use
 @('defattach-system'), which has the same syntax as @('defattach') with two
 exceptions: it adds @(':system-ok t') automatically, that is, @(':system-ok')
 is implicit; and it expands to a @(tsee local) call of @('defattach').  The
 latter is important so that the attachment does not affect system behavior
 outside a book containing the @('defattach') event.  Of course, if it is truly
 intended to affect such behavior, the argument @(':system-ok t') may be given
 directly to @('defattach'), without a surrounding use of @('local').</p>

 <p>See @(see system-attachments) for discussion of system attachments.  Also
 see @(see efficiency) for how to use attachments to modify the prover's
 behavior.</p>")
other
(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)")
other
(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
 })")
other
(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>")
other
(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 appended to the right of any
 explicitly provided :[hints] argument of every @(tsee defthm), @(tsee thm),
 and @(tsee defun) event, and similarly for the @(':guard-hints') argument of
 @('defun'), and, for ACL2(r), the @(':std-hints') argument.</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>")
other
(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>")
other
(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>
 })")
other
(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>")
other
(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>")
other
(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 proving a formula that is, logically
 speaking, a theorem of the current theory, then consider using @(tsee
 skip-proofs) instead.  One such case is the use of a top-down style, as per
 the discussion on ``Top-Down Proof'' in Section B.1.2 of ``Computer-Aided
 Reasoning: An Approach.''  Note that adding new axioms may frequently render
 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>")
other
(defxdoc defbadge
  :parents (apply$ acl2-built-ins)
  :short "Issue a badge for a function so @(tsee apply$) can evaluate with it"
  :long "<p>It is best to be somewhat familiar with the documentation of @(tsee
  apply$) before reading this topic.</p>

  <p>Before using @('defbadge') or a utility like @(tsee defun$) that relies on
  it:</p>

  @({
  (include-book "projects/apply/top" :dir :system)
  })

  <h3>Badges versus Warrants</h3>

  <p>It is easy to confuse @(see badge)s, which are issued by @('defbadge'),
  with @(see warrant)s, which are issued by @(tsee defwarrant).  Badges and
  warrants are necessary to ACL2's support of @(tsee apply$) because ACL2 is
  actually first-order, functions cannot be passed around as objects, ordinary
  symbols play the role of ``function objects,'' and somehow the logic must
  allow the association of a symbol with the function it names.  Furthermore,
  to insure the consistency of the logic @('apply$') is not allowed to handle
  certain functions such as the @('russell') function illustrated in @(tsee
  introduction-to-apply$).  But to determine whether a newly defined function
  is allowed to be known to @('apply$'), the ACL2 system must be able to
  determine, in some sense, all the functions reachable from it.  And finally,
  to be able to prove theorems about the application of such function names,
  the link between the symbols and the functions and the analyzed properties of
  the functions must be available to the prover in the form of axioms.
  Particularly vexing is the so-called ``@('local') problem'' which raises the
  possibility of proving a theorem about the application of a name in the
  context of a local definition of the corresponding function and then
  exporting that theorem to a context where the name is defined
  differently (see <b>Lesson 12</b> of @(see introduction-to-apply$)).</p>

  <p>Roughly speaking, badges are about syntax and warrants are about
  semantics.  The badge for a symbol is a data structure in the ACL2 system
  that records information like whether the symbol names a known ACL2 function,
  how many arguments that function takes, how many results it returns, which
  arguments are treated like function objects to be @(tsee apply$)'d, which are
  treated like expressions to be @(tsee ev$)'d, and which are treated like
  ordinary ACL2 objects to be @('car')'d, @('cdr')'d, consed, etc.  The
  warrant for a function is in fact another function (actually a 0-ary
  predicate) defined in the logic.  That predicate asserts some facts about the
  symbol.  In particular, it specifies the badge of the symbol and it
  constrains the behavior of @('apply$') on the symbol.</p>

  <p>@('Defbadge') analyzes the definition of a function and constructs the
  badge if possible.  @('Defbadge') does not affect the logic &mdash; no
  definitions or axioms are added.  @('Defbadge') can analyze both
  @(':program') mode functions and @(':logic') mode functions.
  @('Defwarrant'), on the other hand, can only analyze @(':logic') mode
  functions because it must inspect the measure used to justify the termination
  of the function and, if it is successful, it adds a @(':logic') mode
  definition of the warrant to the logic.  This definition links the symbol to
  the function via @('badge') and @('apply$') and if the warrant is a
  hypothesis of a conjecture then the prover ``knows'' about the linkage.</p>

  <p>Both @('defbadge') and @('defwarrant') affect the top-level
  read-eval-print loop because that loop treats @(':program') and @(':logic')
  functions differently so that it can (a) allow @(':program') mode terms to be
  evaluated to carry out commands such as @(tsee defun) and @(tsee defthm),
  query the world or build and test prototypes, and (b) allow @(':logic') mode
  terms to be evaluated while guaranteeing a certain correspondence with what
  can be proved.  See @(see guarantees-of-the-top-level-loop).</p>

  <h3>Requirements of @('Defbadge')</h3>

  @({
  General Form:
  (defbadge fn)
  })

  <p>where @('fn') is a defined function name in either @(':')@(tsee program)
  or @(':')@(tsee logic) mode.  This command analyzes the body of @('fn') to
  determine whether it satisfies certain stringent syntactic conditions
  discussed below.  If the conditions are not met, @('defbadge') signals an
  error.  Otherwise, it records a @(see badge) for @('fn').  Badges record the
  input and output arities of @('fn') and specify which arguments are
  ``functions'' that may be applied with @('apply$'), which are ``expressions''
  that may be evaluated with @(tsee ev$), and which are neither.  The
  conditions checked are sufficient to allow @(tsee apply$) to run the function
  safely at the top level of the ACL2 read-eval-print loop.  However, in order
  to prove anything about a call of @('apply$') on @('fn') &mdash; or even to
  evaluate such a call if @('fn') is in @(':')@(tsee logic) mode, as discussed
  above &mdash; @('fn') will need a @(see warrant) as issued by @(tsee
  defwarrant).  @('Defbadge') does not issue warrants, just badges.
  @('Defwarrant') can issue both badges and warrants.</p>

  <p>The first condition on @('fn') is that it must be a defined function
  symbol.  Since @('fn') must be defined it may not be a constrained function
  such as one introduced by @(tsee defchoose) or @(tsee encapsulate).  In
  addition, @('fn') may not be one of a very few ``blacklisted'' symbols (see
  the value of @('*blacklisted-apply$-fns*')) like @(tsee sys-call) (which
  requires a trust tag) or an @(see untouchable).  (For technical reasons,
  untouchables are disallowed even if they are on @('temp-touchable-fns'); see
  @(tsee remove-untouchable).)</p>

  <p>The other conditions depend on whether @(tsee apply$) is reachable from
  @('fn').  That is, can a call of @('fn') lead to a call of @('apply$')?  If
  @('apply$') is not reachable from @('fn'), then there are no more conditions
  on @('fn').  A badge for @('fn') is computed and stored.  We are more precise
  about ``reachability'' later.</p>

  <p>If @('apply$') is reachable from @('fn'), then there are additional
  conditions that must be checked.  First, @('fn') must not have been
  introduced with @(tsee mutual-recursion).  The current badging machinery is
  unable to enforce the syntactic restrictions for mutually-recursive cliques.
  Another restriction is that every function mentioned in the body of @('fn'),
  except @('fn') itself, must already have a badge.  Finally, @('fn') must
  respect certain conventions regarding its use of @(tsee apply$) and other
  @(see scion)s.  The basic idea of this last restriction is to make sure that
  @('apply$') is always called on a ``known'' function symbol or @(tsee lambda)
  object.  This restriction is enforced by checking the following
  conditions:</p>

  <p><i>(a)</i> It must be possible for each formal of @('fn') to be assigned
  one of three @(see ilk)s, @(':FN'), @(':EXPR'), or @('NIL'), as described
  below.  The basic idea is that a formal can be assigned ilk @(':FN') (or ilk
  @(':EXPR')) iff it is sometimes passed into a @(':FN') (or @(':EXPR')) slot
  in the body of @('fn') and is never passed into any other kind of slot.  A
  formal can be be assigned ilk @('NIL') iff it is never passed into a slot of
  ilk @(':FN') or @(':EXPR'), i.e., if it is used exclusively as an
  ``ordinary'' object.  We are more precise below.</p>

  <p><i>(b)</i> Every @(':FN') and @(':EXPR') slot of every function called in
  the body of @('fn') is occupied either by a formal of @('fn') of the same ilk
  or, in the case of calls of functions other than @('fn'), a quoted @(see
  tame) function symbol or quoted tame (preferably well-formed) @('LAMBDA')
  object.  (See @(tsee well-formed-lambda-objectp).)</p>

  <p>This completes the list of restrictions imposed by @('defbadge').</p>

  <h3>Discussion and Examples</h3>

  <p>Note that if @('apply$') is not reachable from @('fn'), the restrictions
  imposed on @('fn') are comparatively generous.  Such a @('fn') could be
  badged and warranted despite being defined mutually recursively or in terms
  of unbadged or even unbadgeable functions.  Basically, if @('fn') doesn't
  depend on @('apply$') there is no danger that some argument of @('fn') will
  be treated like a function object or an expression.</p>

  <p>After a successful @('defbadge') event for @('fn'), the function @(tsee
  badge) will return the computed badge (when executed in the top-level loop)
  and @(tsee apply$) will be able to accept the @('fn') as a functional
  argument.  Here is an annotated script.  First, carry out these two events,
  defining @('foldr') as a @(':program') mode function.</p>

  @({
  (include-book "projects/apply/top" :dir :system)

  (defun foldr (lst fn init)
    (declare (xargs :mode :program))
    (if (endp lst)
        init
        (apply$ fn
                (list (car lst)
                      (foldr (cdr lst) fn init)))))
  })

  <p>Note the @('apply$') call in the definition.  We see that @('foldr')
  treats its middle argument, @('fn'), as a function of arity 2.  We can run
  @('foldr'), even without assigning a badge to @('foldr'), as long as we
  supply a badged function symbol of arity 2 as the middle argument.  Since
  the ACL2 primitive @('cons') has a badge and has arity 2, we can use it:</p>

  @({
  ACL2 !>(foldr '(a b c) 'cons '(d e f))
  (A B C D E F)
  })

  <p>Since @('foldr') has arity 3, we can try to apply it to a list of three
  things.</p>

  @({
  (apply$ 'foldr (list '(a b c) 'cons '(d e f)))

  ACL2 Error in TOP-LEVEL:  The value of APPLY$-USERFN is not specified
  on FOLDR because FOLDR has not been badged.
  })

  <p>However, we can use @('defbadge') to compute and store the badge for
  @('foldr').  The badge says @('foldr') has input arity 3, output arity 1, and
  treats its middle argument as a function.  We can recover the badge by
  calling the function @(tsee badge).  We can successfully apply @('foldr').
  We can even use it in a @('lambda') expression that we pass as the middle
  argument to @('foldr').</p>

  @({
  ACL2 !>(defbadge foldr)

  FOLDR now has the badge (APPLY$-BADGE 3 1 NIL :FN NIL) but has no warrant.
  T

  ACL2 !>(badge 'foldr)
  (APPLY$-BADGE 3 1 NIL :FN NIL)

  ACL2 !>(apply$ 'foldr (list '(a b c) 'cons '(d e f)))
  (A B C D E F)

  ACL2 !>(foldr '((a b c) (d e) (f g h) (i j k))
                (lambda$ (x y)
                  (foldr x 'cons y))
                nil)
  (A B C D E F G H I J K)
  })

  <h3>The ``Reachability'' Test</h3>

  <p>We now clarify the test that we colloquially described above as whether
  @('apply$') is reachable from @('fn').  The actual test is whether
  @('apply$-userfn') is ancestral in @('fn').  That is, does @('fn') call
  @('apply$-userfn'), or a function that calls @('apply$-userfn'), or a
  function that calls a function that calls @('apply$-userfn'), etc.</p>

  <p>Since the only system functions that call @('apply$-userfn') are
  @('apply$'), @('ev$'), and @(see warrant)s, and since it is very unusual for
  a user-defined function to call directly @('apply$-userfn'), @('ev$'), or
  warrants, we think of this test colloquially as whether @('apply$') is
  ancestral in @('fn').</p>

  <p>The test and the onerous conditions imposed when @('apply$') is reachable
  is crucial to the soundness of the ACL2 proof theory.  We discuss this
  further in the background material for @(tsee apply$), including <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 and offer a fully fleshed out metalevel proof that
  @('apply$') and all @(':logic')-mode scions can be modeled in the comment
  titled <tt>Essay on Admitting a Model for Apply$ and the Functions that Use
  It</tt> in the ACL2 source file @('apply-raw.lisp').</p>

  <p>But badges are more concerned with syntax (and, for @(':program') mode
  functions, evaluation) than the proof theory.  Even if we convert @('foldr')
  to @(':logic') mode we cannot prove anything interesting about what happens
  when it is applied with @('apply$').  We can't even prove that @('foldr') has
  a badge or what that badge is!</p>

  @({
  ACL2 !>(verify-termination foldr)
  [Successful.  Output deleted.]
   FOLDR

  ACL2 !>(thm
           (equal (apply$ 'foldr (list x 'cons z))
                  (append x z)))
  [Unsuccessful.  Output deleted.]
  ******** FAILED ********

  ACL2 !>(thm
           (equal (badge 'foldr) '(APPLY$-BADGE 3 1 NIL :FN NIL)))
  [Unsuccessful.  Output deleted.]
  ******** FAILED ********

  })

  <p>In order to prove anything nontrivial about @('foldr')'s badge or behavior
  under @('apply$') we need the @(tsee warrant) for @('foldr').  Warrants are
  issued by @(tsee defwarrant).  If we execute (defwarrant foldr) and then
  amend the failed @('thm') commands above by adding @('(warrant foldr)') as a
  hypothesis, both amended formulas are provable.</p>

  <h3>How Ilks Are Assigned</h3>

  <p>If a formal variable (or its slot among the actuals) has an ilk of
  @(':FN') then the variable is ``used as a function'' in the sense that it
  might eventually reach the first argument of a call of @('apply$') and is
  never passed into an ``ordinary'' slot like those for @('cons').  Similarly,
  an ilk of @(':EXPR') means the variable is ``used as an expression'' and may
  eventually reach the first argument of @('ev$').  An ilk of @('NIL') means
  the variable is never used as a function or an expression.  The correctness
  of this algorithm is crucial to the safe evaluation of @('apply$') on
  user-defined function symbols.  It also is crucial to the termination
  argument justifying the consistency of the proof theory created if and when
  @('fn') is warranted.</p>

  <p>The key to the inductive correctness of the algorithm implicitly described
  below is the fact that when the ACL2 logic is being booted up the only
  function symbol with a slot of ilk @(':FN') is @('apply$') and the only
  function with a slot of ilk @(':EXPR') is @('ev$').  In both functions it is
  the first argument slot that is so distinguished.  All other ACL2 primitives
  that use @('apply$') or @('ev$'), e.g., @('collect$'), are defined,
  admissible, badged, and warranted under the same conditions user-defined
  functions are.</p>

  <p>Let <i>v </i> be the <i>i </i>th formal parameter of a defined function
  <i>fn</i>.  Then the ilk of <i>v </i> is @(':FN') iff the value of <i>v </i>
  eventually makes its way into the first argument of @('apply$'), either in
  the definition of @('fn') or in some function ancestral to (i.e., eventually
  called by) @('fn').  Another way to say this is that there is an occurrence
  of <i>v </i> in a slot of ilk @(':FN').  Furthermore, <i>v </i> is never used
  any other way: every place <i>v </i> occurs in the body of <i>fn </i> is in a
  slot of ilk @(':FN').  And finally, in every recursive call of <i>fn </i>,
  <i>v </i> is passed identically in the <i>i </i>th argument position of the
  call.  We say such a <i>v </i> is ``used (exclusively) as a function.''</p>

  <p>The <i>i </i>th formal variable <i>v </i> has ilk @(':EXPR') under
  analogous conditions except that instead of eventually getting into the first
  argument of @('apply$') it eventually gets into the first argument of
  @('ev$').  We say such a <i>v </i> is ``used (exclusively) as an
  expression.''  Note: @(tsee ev$) is the natural notion of expression
  evaluation in this context: look up the values of variables in the alist
  argument to @('ev$'), return quoted constants, and otherwise @('apply$')
  function symbols and @('LAMBDA') objects to the recursively obtained list of
  values returned by evaluating the actuals.  However, @('ev$') first checks
  that the expression is @(tsee tamep).</p>

  <p>The <i>i </i>th formal variable <i>v </i> has ilk @('NIL') if it never
  occurs in a @(':FN') slot and never occurs in an @(':EXPR') slot.  We say
  such a <i>v </i> is ``used (exclusively) as an ordinary object.''</p>")
other
(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>")
other
(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
    :package package
    :event-name event-name
    :rule-classes rule-classes
    :instructions instructions
    :hints hints
    :otf-flg otf-flg)
 })

 <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'); @('package'), if
 supplied, is one of @(':current'), @(':equiv1'), @(':equiv2'), @(':function')
 or @(':legacy'); @('event-name'), if supplied, is a symbol; 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, in which case @('event-name')
 is used.  The package of symbols generated, such as variables and @(tsee
 defthm) names, is determined by the @('package') argument: if it is not
 supplied or its value is @(':current'), then the @(tsee current-package) is
 used; if its value is @(':equiv1') or @(':legacy'), then the package of
 @(':equiv1') is used; if its value is @(':equiv2'), then the package of
 @(':equiv2') is used; and if its value is @(':function'), then the package of
 @('fn') is used.  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)
 })")
other
(defxdoc defconst
  :parents (events programming)
  :short "Define a constant"
  :long "@({
  Examples:
  (defconst *my-digits* '(0 1 2 3 4 5 6 7 8 9))
  (defconst *len-my-digits* (the unsigned-byte (length *my-digits*)))

  General Form:
  (defconst name term)
 })

 <p>where @('name') is a symbol beginning and ending with the character @('*')
 and @('term') is a variable-free term that is evaluated to determine the value
 of the constant.</p>

 <p>There are two restrictions on @('term') aside from it being variable-free.
 Both restrictions relate to ancestral uses of @(tsee apply$) in @('term'), i.e.,
 uses of @('apply$') by @('term') or any function that might be called during the
 evaluation of @('term').  First, only badged primitive functions may be
 applied.  See @(see badge) for a way to obtain the complete list of badged
 primitives.  Second, @('loop$') and @('lambda$') may not be used anywhere in
 the ancestry of term.  See @('ignored-attachment') and
 @('prohibition-of-loop$-and-lambda$') for more discussion.</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>@('Defconst') sets the @('const') property of @('name') to the quoted value
of @('term'). This can be retrieved with @(tsee getpropc).</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>")
other
(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 equiv
    :package package
    :event-name event-name
    :rule-classes rule-classes
    :instructions instructions
    :hints hints
    :otf-flg otf-flg)
 })

 <p>where @('equiv') is a function symbol of arity 2; @('package'), if
 supplied, is one of @(':current'), @(':equiv') or @(':legacy');
 @('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 @(tsee defthm).  The name of the @(tsee defthm) is
 @('equiv-is-an-equivalence'), unless an @(':event-name') keyword argument is
 supplied, in which case @('event-name') is used.  The package of symbols
 generated, such as variables and @(tsee defthm) names, is determined by the
 @('package') argument: if it is not supplied or its value is @(':current'),
 then the @(tsee current-package) is used; if its value is @(':equiv') or
 @(':legacy') (which are treated identically), then the package of @(':equiv')
 is used.  All other arguments to the generated @(tsee defthm) form are as
 specified by the other keyword arguments above.  The rule-class @(':')@(tsee
 equivalence) is added to the @(see rule-classes) specified, if it is not
 already there.  The term generated for the @(tsee defthm) event states that
 @('equiv') is Boolean, reflexive, symmetric, and transitive. </p>")
other
(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)-(7) 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))))

  (6) How to ev a non-symbol atom:
      [EV-OF-NONSYMBOL-ATOM]
      (implies (and (not (consp x))
                    (not (symbolp x)))
               (equal (ev x a)
                      nil))

  (7) How to ev a cons whose car is a non-symbol atom:
      [EV-OF-BAD-FNCALL]
      (implies (and (consp x)
                    (not (consp (car x)))
                    (not (symbolp (car x))))
               (equal (ev x a)
                      nil))

  (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>")
other
(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)
    dcl ... dcl ; optionally, also one documentation string, as for defun
    (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')
 @(':stobjs'), or @(':dfs').  Any of these 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 that 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>")
other
(defxdoc definductor
  :parents (loop$-recursion)
  :short "Create an induction scheme for a @('loop$')-recursive function"
  :long "<p>@('Definductor') is a utility provided as part of the community
  book @('projects/apply/top'), which should be included in any session dealing
  with @(tsee apply$), @(tsee loop$), or @(tsee loop$-recursion).
  @('(Definductor fn)') attempts to create an induction scheme appropriate for
  the previously defined @('loop$')-recursive function @('fn') and prove an
  @(':')@(tsee induction) rule so that certain calls of @('fn') suggest that
  induction.</p>

  <p><b>Warning:</b> @('Definductor') currently handles a very small class of
  @('loop$')-recursive functions and may produce unhelpful error messages when
  given a function name outside of that class!  We hope to improve it and this
  documentation as we all get more experience with @('loop$')s and
  @('loop$')-recursion.</p>

  @({
  Examples:
  (definductor copy-nat-tree)

  (definductor copy-nat-tree
               :measure (my-measure x)
               :hints (("Goal" :use ...)))

  General Form:
  (definductor name &key measure well-founded-relation ruler-extenders hints)
  })

  <p>where @('name') is the name of a previously admitted @('loop$')-recursive
  function satisfying the restrictions listed below.  When successful it
  defines a function named @('name-INDUCTOR') that suggests an induction scheme
  that is supposedly appropriate for @('name'), admits it with a silent proof
  of its measure theorems, and then proves an @(':')@('induction') rule to
  associate that scheme with calls of @('name').  When omitted, the optional
  keyword arguments @('measure'), @('well-founded-relation'), and
  @('ruler-extenders') default to the measure, well-founded relation, and
  ruler-extender settings used in the admittance of @('name').  The keyword
  argument @('hints') defaults to @('nil').  Note that an appropriate choice of
  @('ruler-extenders') can improve some induction schemes.  See @(see
  induction-coarse-v-fine-grained).</p>

  <h3>Restrictions</h3>

  <p>The given function, @('name'), must satisfy the following restrictions.
  <b>Note:</b> Because we anticipate this utility being further developed in the
  near future this list may not correspond to the latest implementation!</p>

  <ul>

  <li>@('Name') must be a symbol naming a previously admitted @('loop$')-recursive
  function.</li>

  <li>Every recursive @('loop$') in the body of @('name') -- that is, every
  @('loop$') that calls @('name') recursively in the @('when'), @('until'), or
  @('body') clauses of the @('loop$') -- must have as its target(s) distinct
  measured variables or @('cdr')-nests around such variables.</li>

  <li>Every recursive @('loop$') must use @('IN')-iteration, not @('ON')- or
  @('FROM/TO/BY')-iteration.</li>

  </ul>

  <p>While @('definductor') can handle @('loop$') containing multiple @('AS')
  clauses (with targets as described above), it cannot handle @('loop$') such
  as</p>

  @({
  (loop$ for v in (target x) ...)
  (loop$ for v on x ...)
  (loop$ for i from 1 to max ...)
  })

  <p>To see the inductor function generated, type @(':pe name-INDUCTOR').  To
  see examples of the use of @('definductor') inspect the book
  @('projects/apply/definductor-tests.lisp').  To see the definition of
  @('definductor'), see @('projects/apply/definductor.lisp').</p>

  <p>Suggestions for improvements are welcome!  We know of many, including
  allowing the user to specify a different name for the inductor function,
  improving the error messages, printing out the generated @('defun') in the
  event of failure to admit it, and trying to expand the class of
  @('loop$')-recursive functions that can be successfully handled.  We have not
  yet even looked at inductions for @('ON') @('loop$')s and @('FROM/TO/BY')
  @('loop$')s, so that might be easy.  Induction for @('loop$')s over arbitrary
  target expressions may be infeasible!  We just need more examples of
  @('loop$')-recursive functions and successful (hand-written) induction hints
  for them.</p>")
other
(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>")
other
(defxdoc define-pc-macro
  :parents (proof-builder)
  :short "Define a proof-builder macro command"
  :long "<p>A call of @('define-pc-macro') defines a sort of macro, which is a
 tactic that generates @(see proof-builder) instructions.  This topic contains
 basic information about how to use this utility.  For somewhat sophisticated,
 but commented, examples, see the @(see community-book)
 @('books/kestrel/utilities/proof-builder-macros.lisp') and associated tests in
 the same directory, @('proof-builder-macros-tests.lisp').</p>

 <p>We begin with the following example.</p>

 @({
 (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 goal, the above definition of
 @('ib') would let you issue @('ib') and get the same effect.</p>

 @({
 General Form:
 (define-pc-macro cmd args dcl ... dcl body)
 })

 <p>where @('cmd') is the name of the pc-macro that 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.</p>")
other
(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>")
other
(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 @(see clause) &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 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.
 Below we discuss an additional reason that @('supporters') is critical for
 soundness, in the case of dependent clause-processors.</p>

 <p>(Remark.  There could have been two notions of supporters: one for
 functions whose definitions support the correctness of the clause-processor
 function, and, in the case of dependent clause-processors, one for supporters
 of the ``promised encapsulate'' discussed below.  But for simplicity, a single
 @('supporters') argument serves both purposes.)</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 non-@('nil')
 @(':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>Moreover, soundness depends on inclusion of enough function symbols in the
 @('supporters') argument, as follows.  Let @('S') be the set of specified
 @('supporters') augmented by the set of function symbols either introduced by,
 or in a property exported by, the @(':partial-theory') argument, which we call
 the ``promised encapsulate''.  Then every function symbol constrained by the
 promised encapsulate is in @('S').</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-cl-proc-table)').  The resulting alist associates
 each trusted clause-processor with its supporters.</p>

 <p>Note that @('define-trusted-clause-processor') is actually a macro that
 generates (among other things) a @('table') event for extending
 @('trusted-cl-proc-table').  You are invited to use @(':')@(tsee trans1) to
 see expansions of calls of this macro.  In particular, you can see that the
 @(':partial-theory') argument results in an @('encapsulate') event that
 includes a call of the form @('(set-unknown-constraints-supporters f1
 ... fk)'), which in effect makes that call of @('encapsulate') into a call of
 @('partial-encapsulate') with supporters @('(f1 ... fk)').  See @(see
 partial-encapsulate).</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)
    )
 })")
other
(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 much
 as @(':')@(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; but when applying a @(':definition') rule, the result of
 rewriting @('body') must also satisfy 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>")
other
(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>")
other
(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 !>
 })")
other
(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
    dcl ... dcl ; optionally, also one documentation string; see below
    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 whose
 only free variables are the @('macro-args').  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').  Each @('dcl') is an
 optional declaration (see @(see declare)) except that the only @(tsee xargs)
 keyword permitted by @('defmacro') is @(':')@(tsee guard).</p>

 <p>One documentation string may be included between the list of formal
 parameters and the body, but it is essentially ignored by ACL2.  See @(see
 documentation) for a discussion of documentation in ACL2.</p>

 <p>There are two restrictions on @('body') aside from it simply being a term
 in @('macro-args').  Both restrictions relate to ancestral uses of @(tsee
 apply$) in @('body'), i.e., uses of @('apply$') by @('body') or any function
 that might be called during the evaluation of @('body').  First, only badged
 primitive functions may be applied.  See @(see badge) for a way to obtain the
 complete list of badged primitives.  Second, @('loop$') and @('lambda$') may
 not be used anywhere in the ancestry of @('body').  See
 @('ignored-attachment') and @('prohibition-of-loop$-and-lambda$') for more
 discussion.  Note: It is permitted for the value of body to mention
 @('apply$'), @('loop$'), and @('lambda$').</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>")
other
(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>")
other
(defxdoc defmacro-untouchable
  :parents (macros events programming defmacro)
  :short "Define an ``untouchable'' macro"
  :long "<p>Strictly speaking, macros cannot be untouchable the way functions
 are untouchable; see @(see push-untouchable).  However, one can define a macro
 that is, in effect, untouchable, by using @('defmacro-untouchable') to
 introduce a trivial untouchable function into the definition.  Consider for
 example the following definition.</p>

 @({
 (defmacro-untouchable mac (x)
   (list 'consp x))
 })

 <p>Let's look at the single-step macroexpansion of a call of the newly-defined
 macro, @('mac').</p>

 @({
 ACL2 !>:trans1 (mac (f a))
  (PROG2$ (UNTOUCHABLE-MARKER 'MAC)
          (CONSP (F A)))
 ACL2 !>
 })

 <p>We see that this expansion is just as if we had used @(tsee defmacro)
 instead of @('defmacro-untouchable'), except that a @(tsee prog2$) wrapper
 lays down a call of @('untouchable-marker'), which is a built-in untouchable
 function.  In effect, that call makes the macro, @('mac'), untouchable.</p>

 <p>Of course, you are welcome to write your own variant of
 @('defmacro-untouchable'), introducing your own untouchable function.  The
 result would presumably be roughly equivalent to using
 @('defmacro-untouchable'); but using @('defmacro-untouchable') has two
 advantages.  One advantage is that calls of a macro introduced with
 @('defmacro-untouchable') should have no Lisp execution overhead caused by the
 use of @(tsee prog2$) or @('untouchable-marker'), because of special handling
 provided by ACL2 for such calls of @('prog2$') as well as inlining of
 @('untouchable-marker').  The other advantage is that an attempt to use the
 resulting macro without an active trust tag will generally give a more helpful
 error message, mentioning the prior use of @('defmacro-untouchable') as the
 source of the error.</p>")
other
(defxdoc defn
  :parents (defun events)
  :short "Definition with @(see guard) @('t')"
  :long "<p>@('Defn') is @(tsee defun) with @(see guard) @('t').</p>

 <p>@('defn') expands to a @(tsee defun) with an added
 @('(declare (xargs :guard t))').  If an explicit guard is supplied to
 @('defn'), it is conjoined to the added @('t') guard, according to @(tsee
 defun)'s treatment of multiple guard declarations.</p>")
other
(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>

 <p>@('defnd') expands to a @(tsee defund) with an added
 @('(declare (xargs :guard t))').  If an explicit guard is supplied to
 @('defnd'), it is conjoined to the added @('t') guard, according to @(tsee
 defun)'s treatment of multiple guard declarations.</p>")
other
(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, none of whose characters 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>There are two restrictions on @('term') aside from those mentioned above.
 Both restrictions relate to ancestral uses of @(tsee apply$) in @('term'),
 i.e., uses of @('apply$') by @('term') or any function that might be called
 during the evaluation of @('term').  First, only badged primitive functions
 may be applied.  See @(see badge) for a way to obtain the complete list of
 badged primitives.  Second, @('loop$') and @('lambda$') may not be used
 anywhere in the ancestry of term.  See @('ignored-attachment') and
 @('prohibition-of-loop$-and-lambda$') for more discussion.</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.  If @('"MY-PKG"') is the name of the new package and
 @('symb') is the symbol returned by @('(intern (concatenate 'string "MY-PKG"
 "-PACKAGE") "ACL2")'), then @('symb') denotes the @(see rewrite) rule
 added for the package.  For example, here is a display of that rule for the
 event @('(defpkg "MY-PKG" '(a b))').</p>

 @({
 ACL2 !>:pl (pkg-imports "MY-PKG")

 (:REWRITE MY-PKG-PACKAGE)
   New term: '(A B)
   Hypotheses: <none>
   Equiv: EQUAL
   Substitution: NIL

 ....
 })

 <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 not to contain
 lower-case characters.  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.</p>

 <p>NOTE: Also see @(see managing-acl2-packages) for contributed documentation
 on managing ACL2 packages.</p>")
other
(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 it may help to see :DOC raw-lisp-error.

  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>")
other
(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>")
other
(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
    :package package
    :event-name event-name
    :rule-classes rule-classes
    :instructions instructions
    :hints hints
    :otf-flg otf-flg)
 })

 <p>where @('equiv1') and @('equiv2') are known @(see equivalence) relations;
 @('package'), if supplied, is one of @(':current'), @(':equiv1'), @(':equiv2')
 or @(':legacy'); @('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 @(tsee defthm).  The name of
 the @(tsee defthm) event is @('equiv1-refines-equiv2'), unless an
 @(':event-name') keyword argument is supplied, in which case @('event-name')
 is used as the name.  The @('package') of symbols generated, such as variables
 and @(tsee defthm) names, is determined by the @('package') argument: if it is
 not supplied or its value is @(':current'), then the @(tsee current-package)
 is used; if its value is @(':equiv1') or @(':legacy'), then the package of
 @(':equiv1') is used; if its value is @(':equiv2'), then the package of
 @(':equiv2') is used.  The rule-class @(':')@(tsee refinement) 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 other
 keyword arguments above.  The term generated for the @(tsee defthm) event
 states that @('equiv1') refines @('equiv2'). </p>")
other
(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)
            (ht  :type (hash-table eq 70 integer) :initially 0))

  General Form:
  (defstobj name
            (field1 :type type1
                    :element-type etype1
                    :initially val1
                    :resizable b1)
            ...
            (fieldk :type typek
                    :element-type etypek
                    :initially valk
                    :resizable bk)
            :renaming doublets
            :inline flg
            :congruent-to old-stobj-name
            :non-memoizable nm-flg
            :non-executable ne-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), of the form @('(ARRAY type-indicator (max))'), or of one of the forms
 @('(HASH-TABLE test)'), @('(HASH-TABLE test size)'), @('(HASH-TABLE test size
 type-indicator)'), @('(STOBJ-TABLE)'), or @('(STOBJ-TABLE size)'); each
 @('vali') is an object satisfying @('typei'); and each @('bi') is @('t') or
 @('nil').  Pairs @(':element-type etypei'), @(':initially vali'), and
 @(':resizable bi') may be omitted; more on this below.  The @(':renaming
 doublets') 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') and @(':non-executable ne-flg') Boolean arguments
 are ignored when @('nm-flg') and @('ne-flg') are @('nil'), but otherwise: the
 former 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; and the latter avoids actually creating a global
 stobj (details follow later below).  We describe further restrictions on the
 @('fieldi'), @('typei'), @('vali'), and on @('doublets') 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.  For fields of @('ARRAY') type, this
 event also introduces length and resize functions.  For fields of
 @('HASH-TABLE') type, this event also introduces boundp, get?, remove, count,
 clear, and initialization functions.  Fields of @('STOBJ-TABLE') type
 introduce those functions as well except for the get? function.</p>

 <h3>The Single-Threaded Object Introduced</h3>

 <p>The @('defstobj') event effectively introduces a new ``live stobj'' object,
 named @('name'), which has as its initial logical value a list of @('k')
 elements, where @('k') is the number of ``field descriptors'' provided.  This
 object has mutable updates: that is, the object is actually modified in place,
 rather than copied, where for an array or hash-table field the update is made
 to a corresponding raw Lisp array or hash table (respectively).  This is only
 possible because of syntactic restrictions enforced by ACL2 when programming
 with stobjs, so that after modifying a stobj, its old versions are no longer
 accessible.</p>

 <p>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').  If the
 @(':type') of a field is @('(HASH-TABLE test)') or @('(HASH-TABLE test
 size)'), or @('(HASH-TABLE test size type-indicator)'), then: @('test') is one
 of the symbols @('EQ'), @('EQL'), @('HONS-EQUAL'), or @('EQUAL'); @('size'),
 if supplied as above or in @('(STOBJ-TABLE size)'), is nil (handled the same
 as when size is omitted) or a natural number; and @('type-indicator') restrict
 the values that can be stored, as discussed in the next paragraph.  The
 hash-table test is applied when looking up keys in the associated raw Lisp
 hash table, where @(tsee hons-copy) is first applied to the key in the
 @('HONS-EQUAL') case; and the size is a hint to the host Lisp for the initial
 size of the associated hash table in raw Lisp.  (The size really is used only
 as a hint.  Indeed, at least one host Lisp does not support size 0, so ACL2
 simply treats size 0 as size 1; and even size 1 may result in a hash table of
 considerably larger size.)</p>

 <p>If the value of @(':type') is of the form @('(ARRAY type-indicator
 (max))'), @('(HASH-TABLE test size type-indicator)'), or 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>A field with a @('STOBJ-TABLE') type is logically an association list whose
 keys are @(see stobj) names.  ACL2 maintains the execution invariant that each
 key is mapped to a stobj satisfying that key's recognizer.  We say little more
 here about stobj-tables; see @(see stobj-table) for relevant discussion.</p>

 <p>Below, we refer to <i>scalar types</i> as stobj field types that are
 neither array types, hash-table types, nor stobj-table types.  Now consider
 the keyword value @(':initially val') for a stobj field.  If the stobj field
 is of scalar type, then @('val') is the initial value of the field.  For an
 array type @('(ARRAY type-indicator (max))'), @('val') is the initial value of
 the elements in the corresponding array.  For a @('HASH-TABLE') type, @('val')
 is the value obtained when looking up a key that is not bound in the
 hash table; think of it as the default value for lookups.  Finally, the
 @(':initially') keyword is illegal for fields of @('STOBJ-TABLE') type.</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
 primarily 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; see @(see defstobj-element-type) for discussion of the
 @(':element-type') keyword that may be provided for performance .  For fields
 of @('HASH-TABLE') or @('STOBJ-TABLE') type, this event also introduces
 boundp, get? (@('HASH-TABLE') types only), remove, count, clear, and
 initialization functions, as discussed below.  Constants are introduced that
 correspond to the accessor functions.</p>

 <h3>Restrictions on the Field Descriptions in Defstobj</h3>

 <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))'), @('(HASH-TABLE test)'), @('(HASH-TABLE test
 size)'), @('(HASH-TABLE test size type-spec)'), @('(STOBJ-TABLE)'), or
 @('(STOBJ-TABLE size)').  (Again, we are ignoring the case of nested stobjs,
 discussed elsewhere (see @(see nested-stobjs)), where a type-spec may be
 replaced by a stobj name.)  The latter forms are said to be ``array types'',
 ``hash-table types'', and stobj-table types (again, not discussed much here;
 see @(see stobj-table)).  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
  (HASH-TABLE HONS-EQUAL 70)
  (HASH-TABLE EQL NIL (INTEGER 0 *))
  (STOBJ-TABLE 70)
 })

 <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.''  Below we present the
 restrictions on @('typei') and @('vali').</p>

 <p>Remark on @('SATISFIES').  As suggested above, each type indicator must be
 a legal @(see type-spec) or a stobj name.  But if it is a type-spec involving
 @('(SATISFIES pred)'), then not only must @('pred') be a unary @(':')@(tsee
 logic) mode function symbol, but the type-spec is subject to a form of @(see
 guard) verification.  For example, the type-spec @('(SATISFIES evenp)') is not
 legal for a stobj field because the guard generated for @('(evenp x)') is
 @('(integerp x)').  However, the following is legal.</p>

 @({
 (defun my-evenp (x)
   (declare (xargs :guard t))
   (and (integerp x) (evenp x)))
 (defstobj st (fld :type (satisfies my-evenp) :initially 4))
 })

 <p>The following is also legal, as explained below.</p>

 @({
 (defstobj st (a :type (and integer (satisfies evenp)) :initially 0))
 })

 <p>The type-spec displayed immediately above is legal because it generates the
 term @('(and (integerp x) (evenp x)')), which macroexpands to @('(if (integerp
 x) (evenp x) nil)') and hence can be trivially guard-verified.</p>

 <p>To understand this notion of trivial guard verification, first note that
 every type-spec gives rise to a corresponding term in the variable @('x'), as
 in the example just above.  If the type-spec uses @('SATISFIES'), then the
 guard proof obligation for that term is subject to the limited simplification
 used by @(tsee verify-guards) with option @(':guard-simplify :limited'); see
 @(see verify-guards), specifically regarding that option.  The requirement is
 that this limited simplifcation completes the proof, without further
 simplification or a call to the theorem prover.  This restriction to limited
 simplification is probably not much of a restriction for typical uses of
 @('SATISFIES') in type-specs.  End of Remark on @('SATISFIES').</p>

 <h3>Scalar Types</h3>

 <p>We first discuss types that are neither array types, hash-table types, nor
 stobj-table types.  We call these ``scalar 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>

 <h3>Array Types</h3>

 <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>See @(see defstobj-element-type) for how the @(':element-type') field may
 help with performance.</p>

 <h3>Hash-table Types</h3>

 <p>When @('typei') is of the form @('(HASH-TABLE test size type-spec)'), where
 @('size') and @('type-spec') are optional, the field is logically an
 association list, initially empty, accessed using function @(tsee
 hons-assoc-equal) (which is convenient simply because it has a guard of
 @('t'), as opposed to other flavors of @(tsee assoc)).  Under the hood in raw
 Lisp, however, there is a corresponding hash table that represents the same
 association of keys with values as does the association list.  Each key should
 be comparable with arbitrary objects using the specified @('test'): thus if
 @('test') is @(tsee EQUAL) then there is no restriction on keys; if @('test')
 is @(tsee EQ) or @(tsee EQL) then the keys must be symbols or satisfy @(tsee
 eqlablep), respectively; and if @('test') is @(tsee HONS-EQUAL) then there is
 no restriction on keys, but each proposed key is @(tsee hons)ed in raw Lisp
 before it is used (whether for access or update) and before it is put into the
 underlying hash table.  The @('size') defaults to @('nil'), and if supplied,
 it must be either @('nil') or a non-negative integer, or else a defined
 constant evaluating to @('nil') or a non-negative integer.  When the value is
 a (non-negative) integer, it may be used by the host Lisp as a hint for how to
 size the associated hash table in raw Lisp.</p>

 <p>For a hash-table field, the @(':initially') keyword specifies a default
 rather than an initial value: it provides the value (default @('nil'))
 returned by an accessor when a given key is not bound.</p>

 <p>A hash-table field is associated not only with a recognizer, an accessor,
 and an updater, but also with the following functions, whose final argument is
 the stobj name but that may also take a key or, in the case of the ``init''
 function, three other arguments, as follows:</p>

 <ul>

 <li>a ``boundp'' function to check whether a given key is bound;</li>

 <li>a ``get?'' function that, for a given key, returns two values @('(mv val
 boundp)'), where: if the given key is bound then @('val') is its value and
 @('boundp') is @('t'), else @('val') is as specified by the @(':initially')
 keyword (@('nil') by default) and @('boundp') is @('nil');</li>

 <li>a ``remove'' function for removing a given key;</li>

 <li>a ``count'' function that returns the number of (distinct) bound
 keys;</li>

 <li>a ``clear'' function that creates a new empty hash table (and logically,
 the empty alist);</li>

 <li>an ``init'' function that takes a given size, rehash-size, and
 rehash-threshold (and the stobj name) and creates a new empty hash table (and
 logically, the empty alist) by passing these parameters to the raw Lisp
 function, @('(make-hash-table)'), that creates a hash table.</li>

 </ul>

 <p>The clear and init functions both use the @('size') argument, if supplied
 and not @('nil'), of the type of the field supplied in the @('defstobj')
 event.  If a non-@('nil') @('size') argument was not supplied in that type,
 then the size of the hash table depends on the host Lisp.</p>

 <h3>Stobj-table Types</h3>

 <p>As noted above, these are not discussed much here; see @(see
 stobj-table).</p>

 <h3>The Default Function Names</h3>

 <p>To recap, in</p>

 @({
  (defstobj name
            (field1 :type type1 :initially val1)
            ...
            (fieldk :type typek :initially valk)
            :renaming doublets
            :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, hash-table, and stobj-table 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>The accessor and updater functions for a hash-table field are analogous to
 those for array fields.  Thus, the accessor takes an additional key argument
 and returns the associated value, or nil if the key is not bound.  The updater
 function takes a key, a new value, and the stobj, and returns a new stobj with
 the indicated element replaced by the new value.  See @(see stobj-table) for a
 discussion of stobj-table types, which are largely ignored below.</p>

 <p>These functions &mdash; the recognizer, accessor, and updater, and also
 length and resize functions in the case of array fields, and boundp, get?,
 remove, count, clear, and init functions in the case of hash-table fields
 &mdash; have ``default names.''  The default names depend on the field name,
 @('fieldi'), and on whether the field is an array field, a hash-table field,
 or neither (i.e., a scalar field).  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 or the size of a
 resized array, @('k') as a key (for the logical association list or raw-Lisp
 hash table associated with the field), @('v') as the ``new value'' to be
 installed by an updater, and @('name') as the single-threaded object.</p>

 @({
              scalar field        array field          hash-table field
                                                       and stobj-table field
  recognizer  (cP x)              (cP x)               (cP x)
  accessor    (c name)            (cI i name)
                                      hash-table access: (c-get k name)
                                     stobj-table access: (c-get k name default)
  updater     (UPDATE-c v name)   (UPDATE-cI i v name) (c-put k v name)
  length                          (c-LENGTH name)
  resize                          (RESIZE-c i name)
  boundp                                               (c-boundp k name)
  get? [For hash-tables only, not stobj-tables]        (c-get? k name)
  remove                                               (c-rem k name)
  count                                                (c-count name)
  clear                                                (c-clear name)
  init                                                 (c-init ht-size
                                                               rehash-size
                                                               rehash-threshold
                                                               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)
    (H :TYPE (HASH-TABLE EQ)))
 })

 <p>introduces a stobj named @('$S').  The stobj has three fields: @('X'),
 @('A'), and @('H').  The @('A') field is an array and the @('A') field is
 a hash table.  The @('X') field contains an integer and is initially 0.  The
 @('A') field contains a list of integers, each between 0 and 9, inclusive.
 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 HP (X) ...)               ; recognizer of H 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 (I $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
  (DEFUN H-GET (K $S) ...)         ; accessor for H field at key K
  (DEFUN H-PUT (K V $S) ...)       ; updater for H field at key K
  (DEFUN H-BOUNDP (K $S) ...)      ; t if key k is bound in H, else nil
  (DEFUN H-GET? (K $S) ...)        ; (mv val t) if key is bound in H to val;
                                   ;   (mv nil nil) if key is not bound in H
  (DEFUN H-REM (K $S) ...)         ; remove key K from field H
  (DEFUN H-COUNT ($S) ...)         ; the number of (distinct) keys in field H
  (DEFUN H-CLEAR ($S) ...)         ; empty the hash table for field H
  (DEFUN H-INIT (HT-SIZE REHASH-SIZE REHASH-THRESHOLD $S) ...)
                                   ; replace the hash table for field H with
                                   ;   with a new, empty hash table with the
                                   ;   given hints as described below
 })

 <p>For the last of these, the values of @('HT-SIZE'), @('REHASH-SIZE'), and
 @('REHASH-THRESHOLD') are passed to the @(':size'), @(':rehash-size'), and
 @(':reash-threshold') arguments (respectively) of a call of
 @('make-hash-table') in raw Lisp.  The @(':test') argument of this function is
 the one specified in the @(':type') specified in the @('defstobj') event for
 the field, in this case @('EQ') from the type @('(HASH-TABLE EQ)'); note
 however that if the @(':type') specifies the test @('HONS-EQUAL'), then the
 @(':test') is @('EQL').</p>

 <h3>Avoiding the Default Function Names</h3>

 <p>If you do not like the default names listed above you may use the optional
 @(':renaming') doublets to substitute names of your own choosing.  Each
 element of @('doublets') 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 doublets 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') doublets may be necessary to avoid name clashes
 between the default names and pre-existing function symbols.</p>

 <h3>Constants</h3>

 <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>

 <h3>The Effects of a <tt>Defstobj</tt></h3>

 <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.  Those
 functions that contain @('(DECLARE (STOBJ-INLINE-FN T))') will generate @(tsee
 defabbrev) forms because the @(':inline') keyword of @('defstobj') was
 supplied the value @('t').  The rest will generate @(tsee defun) forms.</p>

 <p>Evaluation of a @('defstobj') event @(see disable)s the @(see
 executable-counterpart) of the creator function.  This is useful for proofs,
 since calls of that function always cause an error (albeit one which is
 handled during proofs).</p>

 <p>A @('defstobj') is considered redundant only if it is syntactically
 identical to a previously executed @('defstobj').  Note that a redundant
 @('defstobj') does not reset the @(see stobj) fields to their initial
 values.</p>

 <h3>Performance</h3>

 <p>The @(':inline') keyword argument controls whether or not the functions
 introduced are inlined (as macros under the hood, in raw Lisp), with the
 exception of the resize function.  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 perhaps 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 an 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>It can also improve performance to specify @(':non-memoizable t'), which
 disallows memoization but therefore avoids the cost of certain ``flushing''
 operations.</p>

 <p>See @(see defstobj-element-type) for performance considerations pertaining
 to the @(':element-type') field.</p>

 <h3>Specifying Congruent Stobjs</h3>

 <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 !>
 })

 <h3>Specifying Non-executable Stobjs</h3>

 <p>As noted above, if keyword argument @(':non-executable t') is specified
 then no global stobj for the given name is created.  See @(see
 add-global-stobj) for a discussion of global stobjs, but in a nutshell, a
 global stobj is a ``live'', mutable stobj that can be referenced in the
 top-level loop.  So why use this keyword argument?  Perhaps you would like to
 do your computation on several stobjs that are all congruent to a given stobj,
 @('st').  Then by using @(':non-executable t') to introduce @('st'), you avoid
 allocating memory for @('st') that you never intend to use.  Similarly, you
 can avoid allocating such memory when your intended use of @('st') is only as
 a local stobj (see @(see with-local-stobj)) or as the type of a stobj field of
 another stobj.  But see @(see add-global-stobj) and @(see remove-global-stobj)
 for utilities that change whether or not there is a global stobj for a given
 name.</p>")
other
(defxdoc defstobj-element-type
  :parents (defstobj)
  :short "Specify the element type for a @(see stobj) array field"
  :long "<p>This topic assumes familiarity with the @(tsee defstobj) event.  It
 documents the @(':element-type') keyword for a stobj array field.  Note that
 @(':element-type') is only supported for stobj array fields, not other sorts
 of stobj fields.</p>

 <p>Consider a stobj array field with @(':type') of the form @('(array
 etype (n))'), for example, @('(array bit (8))').  Logically, this
 &ldquo;array&rdquo; is a list, each of whose elements has the indicated type,
 @('etype') &mdash; in our example, the type, @('bit') (i.e., 0 or 1).  In raw
 Lisp, however, an array is allocated.  The Lisp code that allocates that array
 can specify the type of its elements, and may specify that element type to be
 @('bit').  But it would also be legal to specify a weaker type.  In particular,
 the type @('t') is a legal type for every object, and this can be specified by
 including @(':element-type t') in your stobj array field.</p>

 <p>Perhaps surprisingly, Lisp code may run faster when the element type in a
 raw Lisp array is @('t') rather than a more restrictive type.  The
 @(':element-type') of a stobj array field may be specified to be @('t') to
 give this behavior, by using @(':element-type t').  You can do your own
 experiments to decide whether that is helpful, in particular by considering
 @(see community-book) @('books/demos/element-type.lisp').  That file starts
 with the following events and then times reading and writing the stobj
 array.</p>

 @({
 (defconst *ar-size* (expt 10 8))
 (defstobj st1
   (ar1 :type (array double-float (*ar-size*))
        :element-type t ; Omit this line to compare times with or without it.
        :initially 0)
 ; Optional:
   :inline t)
 })

 <p>Our own experiments with this file have produced the following results (for
 both realtime and runtime) with CCL and SBCL on a 2019-era MacBook Pro (2.4
 GHz 8-Core Intel Core i9).  They suggest the use of @(':element-type t') with
 read-intensive applications when using CCL.  Results may be very different
 without the use of @(':inline t'), and of course these results may not be
 indicative of your own experience with various applications, Lisps, and
 operating systems.</p>

 @({
 (time$ (reads-st1 st1 *ar-size*))
 Results:
   CCL
     With :element-type t
       0.27 seconds (32 bytes allocated)
     Without :element-type t
     ; 0.47 seconds (32 bytes allocated)
   SBCL
     With :element-type t
       0.23 seconds (0 bytes allocated)
     Without :element-type t
       0.21 seconds (0 bytes allocated)

 (time$ (writes-st1 st1 (to-df 2) *ar-size*))
 Results:
   CCL
     With :element-type t
       1.17 seconds (128 bytes allocated);
     Without :element-type t
       0.27 seconds (128 bytes allocated)
   SBCL
     With :element-type t
       0.24 seconds realtime (0 bytes allocated)
     Without :element-type t
       0.25 seconds (0 bytes allocated).
 })

 <p>Currently the legal values for @(':element-type') are @('t') and the
 default value, which is the element type specified in the @(':type') field of
 the stobj array field specification.  This could change if experiments suggest
 something different.</p>")
other
(defxdoc defstub
  :parents (events)
  :short "Stub-out a function symbol"
  :long "@({
 Examples:
 ACL2 !>(defstub subr1 (* * state) => (mv * state))
 ACL2 !>(defstub add-hash (* * hashtable) => hashtable)
 ACL2 !>(defstub inv (*) => * :formals (x) :guard (fieldp x))

 General Forms:
 (defstub name (i1 ... ik) => outputs :kwd1 val1 ... :kwdn valn) ; new style
 (defstub name (i1 ... ik) outputs :kwd1 val1 ... :kwdn valn)    ; old style
 })

 <p>where @('name') is a new function symbol, and @('(i1 ... ik)'),
 @('outputs'), @(':kwdi'), and @('vali') must be as follows, respectively.</p>

 <ul>

 <li><i>New style:</i> @('((name i1 ... ik) => outputs :kwd1 val1 ... :kwdn
 valn)') is a valid new-style @(see signature).</li>

 <li><i>Old style:</i> @('(name (i1 ... ik) outputs :kwd1 val1 ... :kwdn
 valn)') is a valid old-style @(see signature).</li>

 </ul>

 <p>Also see @(see signature).  Note that @('(i1 ... ik)') is the
 list of formal parameters of the newly-defined function symbol, @('name').</p>

 <p>Note that while the @('defstub') syntax resembles a @(see signature), it is
 different: @('name') occurs outside the parentheses containing @('(i1
 ... ik)') in the @('defstub') syntax, but inside in the signature syntax.</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 @('outputs') is of the form @('(mv ...)'), then a @(':')@(tsee
 type-prescription) rule is introduced stating that @('name') returns a value
 satisfying @(tsee true-listp).</p>")
other
(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 60 @(see rune)s as of
 ACL2 Version  8.6:</p>

 @({
  ACL2 !>(deftheory foo (union-theories '(binary-append)
                                        (theory 'minimal-theory)))

  Summary
  Form:  ( DEFTHEORY FOO ...)
  Rules: NIL
  Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
   60
  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>")
other
(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>")
other
(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>")
other
(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 the following, except that some output is inhibited for the
 @(tsee in-theory) and @(tsee value-triple) @(see events):</p>

 @({
  (progn
    (defthm NAME TERM ...)
    (in-theory (disable NAME))
    (value-triple '(:defthmd NAME))).
 })

 <p>@('Defthmd') events are generally not redundant, because the generated
 @(tsee in-theory) event is not redundant.  This default can be changed; see
 @(see set-in-theory-redundant-okp).</p>

 <p>See @(see defthm) for documentation of @('defthm').</p>")
other
(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>")
other
(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 that contain calls of @(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 @(see 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') names 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 functions, including @(tsee sys-call); evaluate the form
 @('(strip-cars *ttag-fns*)') to see the full list of such symbols.  The macro
 @(tsee progn!)  similarly requires an active ttag.  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 may be
 restricted according to the @(':ttags') keyword argument.  If this argument is
 @('nil') 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 book's absolute
 pathname, 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>")
other
(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)
    dcl ... dcl ; optionally, also one documentation string; see below
    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>See also @(see mutual-recursion) for how to use @('defun') to make mutually
 recursive definitions, including discussion of how the @(tsee xargs) @(see
 declaration)s in one @('defun') may affect the other definitions.</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).</p>

 <p>The <i>declarations</i> (see @(see declare)), @('dcl'), are 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>One documentation string may be included between the list of formal
 parameters and the body, but it is essentially ignored by ACL2.  See @(see
 documentation) for a discussion of documentation in ACL2.</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 ruling the call are
 satisfied (see @(see rulers)).  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 default well-founded relation is @(tsee o<), an ``ordinal less-than''
 relation (discussed further below) that reduces to ordinary @('<') on the
 natural numbers.  The default measure term is @('(acl2-count var)'), where
 @('var') is a formal parameter that is chosen heuristically: roughly speaking,
 it is the first formal that is tested along every branch and changed in each
 recursive call.</p>

 <p>The only primitive well-founded relation in ACL2 is @(tsee o<), which is
 known to be well-founded on the @(tsee o-p)s.  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.
 See @(see induction-coarse-v-fine-grained) for a discussion of how well-chosen
 rulers can affect the induction scheme.</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, but it
 is completely nonsensical and it shows only a few of the many @(':xargs')
 keywords.  See @(see xargs) for a complete list of @(':xargs') keywords; also
 see @(see hints).</p>

 @({
  (defun example (x y z a b c i j)
    (declare (ignore a b c)
             (ignorable x y)
             (irrelevant c)
             (type integer i j)
             (optimize (safety 3))
             (xargs :guard (symbolp x)
                    :measure (- i j)
                    :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
                    :verify-guards nil
                    :type-prescription (natp (example x y z a b c i j))))
    (example-body x y z i j))
 })")
other
(defxdoc defun$
  :parents (defun events apply$)
  :short "Define a function symbol and generate a warrant"
  :long "<p>@('Defun$') is just a macro that expands to the obvious @(tsee
  defun) followed by @(tsee defwarrant).</p>")
other
(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)
    dcl ... dcl ; optionally, also one documentation string; as for defun
    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').  The documentation string 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 suffix restrictions are explained in
 a comment in the ACL2 source definition of macro @('defun-inline').  Note that
 only the functions themselves are thus proclaimed, not their executable
 counterparts (also known as *1* functions; see @(see evaluation)).</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.</p>")
other
(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.  One restriction is that
 every function called by the newly defined one must be in @(':logic') mode.
 (However, see @(see defun-mode-lambdas) for some clarification concerning
 @(tsee apply$).)  But the most challenging restriction is that the system must
 prove that the recursion in the new definition terminates.</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>")
other
(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>")
other
(defxdoc defun-mode-lambdas
  :parents (defun-mode)
  :short ":program mode functions in @(tsee LAMBDA) objects"
  :long "<p>A rough rule-of-thumb is that all functions mentioned in a
  @(':')@(tsee logic) mode @(tsee defun) must themselves be in @(':logic')
  mode.  If @('prgm') is a @(':')@(tsee program) mode function then @('(defun
  fn (x) (prgm x))') is illegal.  But there are situations (always involving
  @(tsee apply$)) in which @(':program') mode function symbols are allowed to
  be mentioned in @(':logic') mode @(tsee defun)s.  We explain here.</p>

  <p>Here are two example terms that mention the badged (see @(tsee defbadge))
  @(':program') mode symbol @('prgm').</p>

  @({
  (apply$ (lambda$ (e) (prgm e)) (list x))

  (loop$ for e in lst collect (prgm e))
  })

  <p>Are such terms permitted in the @('defun') of a @(':logic') mode function?
  The answer is complicated because it depends on whether the @('defun') is
  @(tsee loop$) recursive and whether the @('defun') will also try to verify
  the @(tsee guard)s of @('fn').</p>

  <p>First, a @(':logic') mode function may @('apply$') a quoted @(':program')
  mode symbol, whether guards are being verified or not.  For example,
  @('(apply$ 'prgm args)') is legal.  Here @('prgm') is just a quoted symbol.
  Since @('prgm') is a @(':program') mode symbol, there are no axioms about it,
  so during proofs such a call of @('apply$') is not evaluated or expanded.  If
  this form is evaluated at the top-level -- where @(':program') mode functions
  are evaluable -- @('apply$') checks the guards of @('prgm') just as it would
  before any @(':program') mode function is called.</p>

  <p>The situation is more complicated for use of @(':program') mode functions
  in forms like @(tsee lambda$), well-formed quoted @(tsee LAMBDA) objects, and
  @(tsee loop$).  The reason is that in guard-verified code, these forms are
  generally executed via compiled code and that requires that the @('loop$')
  and @('lambda') objects be Common Lisp compliant, which in turn implies they
  must be analyzable by the prover.  Since formally @('loop$')s are understood
  as calls of @(see scion)s on @('lambda$') expressions it suffices for us to
  discuss the @('lambda$') case alone.  Well-formed quoted @('LAMBDA') objects
  are treated the same way.</p>

  <p>So again, suppose you're defining a @(':logic') mode function @('fn').
  Suppose @('fn') is not @('loop$') recursive and guards are not being verified
  during the @('defun').  Then badged @(':program') mode symbols may be used
  @('lambda$') forms in the definition of @('fn').</p>

  <p>If @('fn') is @('loop$') recursive, i.e., @(':')@(tsee loop$-recursion)
  @('t') is declared, then all symbols used as functions in @('lambda$') forms
  must be in @(':logic') mode.  The reason is that the measure conjectures
  generated must be in @(':logic') mode to be provable.</p>

  <p>If @('fn') is to be guard-verified, then all symbols used as functions in
  @('lambda$') forms must be in @(':logic') mode.  The reason is that the guard
  conjectures must be in @(':logic') mode to be provable.</p>

  <p>When a @(':program') function is permitted in a @(':logic') mode definition
  the system will print a warning to alert you to the possibility that proofs
  will fail.  For example, the following events are legal</p>

  @({
  (include-book "projects/apply/top" :dir :system)

  (defun prgm (x)
    (declare (xargs :mode :program))
    (list 'hi x))

  (defbadge prgm)

  (defun fn1 (x)
    (declare (xargs :mode :logic))
    (apply$ 'prgm (list x)))
  })

  <p>but the last event will print:</p>

  @({
  ACL2 Warning [Problematic-quoted-fns] in ( DEFUN FN1 ...): The definition of
  FN1 is in :LOGIC mode but mentions the :PROGRAM mode function HELLO in one or
  more :FN or :EXPR slots.  Conjectures about FN1 may not be provable until
  this program is converted to :LOGIC mode and warranted!  See :DOC
  verify-termination and defwarrant.
  })

  <p>Uses of @('prgm') in quoted well-formed @('LAMBDA') objects, @('lambda$')
  forms, and @('loop$') forms will cause similar warning messages to be
  printed.</p>")
other
(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>")
other
(defxdoc defun-nx
  :parents (defun events)
  :short "Define a non-executable function symbol"
  :long "@({
  Example:

  (defun-nx foo (x state)
    (declare (xargs :guard t))
    (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)
    (declare (xargs :stobjs state))
    (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>generates the following definition.</p>

 @({
  (defun name (x1 ... xk)
    (declare (xargs :non-executable t :mode :logic))
    ...
    (prog2$ (throw-nonexec-error 'name (list x1 ... xk))
            body))
 })

 <p>But @('defun-nx') does two other things.  Before executing the @('defun')
 form displayed above, ACL2 arranges that @('state') is allowed as a formal
 parameter, by first introducing @('(set-state-ok t)') in a way that is @(see
 local) to the generated event.  After executing the @('defun'), the @(see
 executable-counterpart) @(see rune) for @('name') is @(see disable)d.  You can
 evaluate @(':trans1 (defun-nx ...)') for your @('defun-nx') form to see its
 single-step macroexpansion.</p>

 <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 @(tsee defund-nx) is also available.  It is essentially identical
 to @('defun-nx') except that as with @(tsee defund), @('defund-nx') leaves the
 definition @(see rune) disabled for the new function symbol.</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>")
other
(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 strengthen constrain
    verbose)
 })

 <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, and the call above 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 (or a corresponding rule; see the discussion of
 @(':constrain') below) 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, for example in the passing of
 multiple values.  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 if you prefer that @(tsee defun)
 be used instead of @('defun-nx'), you can arrange that using @(tsee declare)
 forms, given as the @('dcl_i') as shown above.  These will become the
 @('declare') forms in the generated @(tsee defun).  If the @(tsee xargs) @(see
 declaration) form @(':non-executable nil') is supplied, then @(tsee defun)
 will be used in place of @(tsee defun-nx).</p>

 <p>@(csee Guard) verification is performed for @('defun-sk') events under the
 same conditions as for @('defun') events.  (An exception, ignored here but
 discussed in a later paragraph below, occurs when keyword argument
 @(':constrain t') is supplied.)  Thus, by default, guard verification will be
 attempted exactly when at least one of @('type'), @(':guard'), or
 @(':verify-guards t') is specified in a declaration (that is, in some
 @('dcl_i').  This default behavior can be modified just as it is for
 @('defun'); see @(tsee set-verify-guards-eagerness).  Technical note: 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).  You can use the command @(':')@(tsee
 pcb!) to see the event generated by a call of the @('defun-sk') macro.  If you
 want to watch the subsidiary events (including the @('defchoose') event) as
 they are being executed, use keyword option @(':verbose t').</p>

 <p>An advanced feature is argument @(':strengthen t'), which generates 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.</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>There is one more keyword argument not explained above: @(':constrain').
 The default is @('nil'); otherwise this argument must be a symbol, which we
 call @('name-def'), except that in the case of @('t'), @('name-def') is
 obtained by adding the suffix @('"-DEFINITION"') to @('fn').  For a
 non-@('nil') @(':constrain') argument, this @('name-def') is the name of a
 rule of class @(':')@(tsee definition) that equates @('(fn var1 ... varn)')
 with the body of the definition of @('fn').  Furthermore, in this case of a
 non-@('nil') @(':constrain') value the definition of @('fn') is local to the
 surrounding @('encapsulate'), which contains a signature for @('fn').  As
 usual, the simplest way to see the effects of @(':constrain') may be to apply
 @(':trans1') to your @('defun-sk') form.  Note that constraining the function
 can make it possible to attach to it (see @(see defattach)) and to introduce
 it as a @(see guard)-verified function.  Also note that when @(':constrain t')
 is specified: the guard of @('fn') will automatically be @('t'), no guard
 verification will be performed, and @('fn') will nevertheless be a
 guard-verified (and constrained) function.</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 in the first half of the 20th century!  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>")
other
(defxdoc defun-sk-example
  :parents (defun-sk)
  :short "A simple example using @(tsee defun-sk)"
  :long "<p>For a more thorough, 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))))))))
 })")
other
(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 @(see
 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 the following, except that some output is inhibited for the
 @(tsee in-theory) event:</p>

 @({
  (progn
    (defun NAME FORMALS ...)
    (in-theory (disable NAME))
    (value-triple '(:defund NAME))).
 })

 <p>Only the @(':')@(tsee definition) rule and, for recursively defined
 functions, the @(':')@(tsee induction) rule are disabled for the function.
 In particular, @('defund') does not disable either the @(':')@(tsee
 type-prescription) or the @(':')@(tsee executable-counterpart) rule.</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>@('Defund') events are generally not redundant, because the generated
 @(tsee in-theory) event is not redundant.  This default can be changed; see
 @(see set-in-theory-redundant-okp).</p>

 <p>See @(see defun) for documentation of @('defun').</p>")
other
(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>")
other
(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>")
other
(defxdoc defund-nx
  :parents (defun events)
  :short "Define a disabled non-executable function symbol"
  :long "<p>Use @('defund-nx') instead of @(tsee defun-nx) when you want to
 @(see disable) the definition of a function symbol immediately after defining
 it in @(':')@(tsee logic) mode.  In all other respects, @('defund-nx') has the
 same behavior as @('defun-nx'); See @(see defun-nx) for details.  Also see
 @(see defund).</p>")
other
(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>")
other
(defxdoc defwarrant
  :parents (apply$ acl2-built-ins)
  :short "Issue a warrant for a function so @(tsee apply$) can use it in proofs"
  :long "<p>It is best to be somewhat familiar with the documentation of @(tsee
  apply$) before reading this topic.</p>

  <p>Before using @('defwarrant') or a utility like @(tsee defun$) that relies
  on it:</p>

  @({
  (include-book "projects/apply/top" :dir :system)
  })

  <p>Several lemmas in that book are necessary for @('defwarrant') to prove
  the theorems it must prove.</p>

  <h3>Badges versus Warrants</h3>

  <p>It is easy to confuse @(see badge)s, which are issued by @(tsee defbadge),
  with @(see warrant)s, which are issued by @('defwarrant').  See the first
  section of @(tsee defbadge) for an extended discussion.</p>

  <h3>Requirements of @('Defwarrant')</h3>

  @({
  General Form:
  (defwarrant fn)
  })

  <p>where @('fn') is a defined function name.  This command analyzes the body
  of @('fn') to determine whether it satisfies certain stringent syntactic and
  semantic conditions that allow the ACL2 proof theory to be extended so that
  the prover can simplify forms like @('(apply$ 'fn ...)').  The syntactic
  conditions include those of @(tsee defbadge), which @('defwarrant')
  essentially invokes if @('fn') is a @(':')@(tsee logic) mode function that is
  not already badged.  But below we describe all the conditions checked by
  @('defwarrant') since many users use @('defwarrant') to issue both a badge
  and a warrant.</p>

  <p>Basic conditions include that @('fn') is in @(':')@(tsee logic)-mode and
  that its justification (i.e., the measure, well-founded relation, and domain
  predicate used to admit @('fn')) be expressible without any reference to
  @(tsee apply$), @(tsee ev$), or @(tsee apply$-userfn).</p>

  <p>@('Defwarrant') imposes some additional conditions on @('fn'), but exactly
  what those conditions are depends on a certain ``reachability'' test detailed
  in the section titled <b>The ``Reachability'' Test</b> in @(tsee defbadge).
  Roughly speaking the test is whether @('apply$') is ancestral in @('fn'),
  meaning @('apply$') is somehow involved in the definition of @('fn') or the
  functions it calls.</p>

  <p>If the reachability test succeeds &mdash; colloquially, if @('fn') depends
  on @('apply$') &mdash; then @('defwarrant') imposes the following additional
  conditions in order to issue a warrant.</p>

  <p><i>(a)</i> If @('fn') is recursive it must not be part of a mutually
  recursive clique and its measure must be of type @(tsee NATP) or be a
  lexicographic combination of natural numbers as defined by the @('llist')
  function in the Community Books at @('books/ordinals/').</p>

  <p><i>(b)</i> Every function called in the body of @('fn'), except @('fn')
  itself, must already have a @(see badge) and a warrant.  If some subfunction
  doesn't already have a badge, @('defwarrant') will call @(tsee defbadge) and
  signal an error if that fails.  If some subfunction doesn't already have a
  warrant, @('defwarrant') will signal an error and suggest that you call
  @('defwarrant') on the offending subfunction first.  @('Defwarrant') will
  continue to fail until all subfunctions have badges and warrants.</p>

  <p><i>(c)</i> It must be possible for each formal of @('fn') to be assigned
  one of three @(see ilk)s, @(':FN'), @(':EXPR'), or @('NIL'), as described
  below.  The basic idea is that a formal can be assigned ilk @(':FN') (or ilk
  @(':EXPR')) iff it is sometimes passed into a @(':FN') (or @(':EXPR')) slot
  in the body of @('fn') and is never passed into any other kind of slot.  A
  formal can be be assigned ilk @('NIL') iff it is never passed into a slot of
  ilk @(':FN') or @(':EXPR'), i.e., if it is used as an ``ordinary'' object.
  We are more precise below.</p>

  <p><i>(d)</i> Every @(':FN') and @(':EXPR') slot of every function called in
  the body of @('fn') is occupied either by a formal of @('fn') of the same ilk
  or, in the case of calls of functions other than @('fn'), a quoted @(see
  tame) function symbol or quoted tame (preferably well-formed) @('LAMBDA')
  object.</p>

  <p>This completes the list of additional restrictions imposed by
  @('defwarrant') on @('fn'), when @('apply$') is reachable from @('fn').</p>

  <p>If the reachability test fails &mdash; colloquially, if @('fn') does not
  depend on @('apply$') &mdash; then @('defwarrant') just checks that @('fn')
  does not call any of a few functions that @('apply$') is prohibited from
  running.  Among those blacklisted functions are @(tsee sys-call) and other
  functions requiring a trust tag.  For a list of the blacklisted functions see
  the value of @('*blacklisted-apply$-fns*').</p>

  <p>Note that the restrictions imposed on functions from which @('apply$')
  cannot be reached are comparatively generous.  If @('fn') does not depend on
  @('apply$') then @('fn') can be warranted despite (a) being defined mutually
  recursively or with an arbitrary ordinal measure, or (b) calling unbadged or
  unbadgeable functions.  @('Defwarrant') can be relaxed in this case because
  the warrant constrains @('(apply$ 'fn ...)') to be @('(fn ...)') and @('fn')
  is a well-defined @(':logic') mode function that is independent of
  @('apply$').  Thus, in the model of @('apply$') that justifies the whole
  @('apply$') story, the handling of @('fn') is just a base case.  The
  situation would be more restrictive if the warrant constrained @('(apply$ 'fn
  ...)') to evaluate the body of @('fn') with @(tsee ev$) which would possibly
  raise termination issues.</p>

  <p>Regardless of whether @('apply$') is reachable, if the requisite
  conditions are not met, @('defwarrant') causes an error.</p>

  <p>If the requisite conditions are met, @('defwarrant') obtains or constructs
  the @(see badge) for @('fn'), setting the arity and out arity appropriately
  and setting the ilks field to the list of computed ilks (or to @('T') if
  every formal has ilk @('NIL')).  The generated badge is stored for the future
  use of @('defwarrant').  See @(tsee defbadge) for a brief discussion of how
  ilks are computed.</p>

  <p>Furthermore, @('defwarrant') generates the @(tsee warrant) for @('fn').
  The name of that 0-ary function will be @('APPLY$-WARRANT-fn').  Calls of
  @(tsee apply$) on @(''fn') in proof attempts can only be simplified if the
  warrant hypothesis, @('(APPLY$-WARRANT-fn)'), <i>aka</i> ``the warrant,'' is
  among the hypotheses of the conjecture being proved.  The warrant specifies
  the values of both @('(badge 'fn)') and @('(apply$ 'fn ...)'), including the
  tameness requirements imposed on @('apply$').  (The warrant explicitly
  specifies the values of @(tsee badge-userfn) and @(tsee apply$-userfn) and
  then @(tsee defwarrant) proves rewrite rules to make calls of @('badge') and
  @('apply$') simplify accordingly.)</p>

  <p>If a warrant is issued for @('fn'), then @('defwarrant') also extends
  ACL2's evaluation theory (but not its proof theory) so that the warrant
  hypothesis is assumed true in that theory, allowing calls of @('badge') and
  @('apply$') to be evaluated in the evaluation theory (but not in the proof
  theory).  See @(tsee warrant) for details.</p>

  <p>You might worry that theorems burdened by warrants are vacuously valid
  because it might be impossible to satisfy all the warrant hypotheses.  You
  needn't worry about this.  <i>There is a model of @('apply$') and all of its
  @(tsee scion)s that makes every warrant issued by @('defwarrant') valid.</i>
  The proof of this is sketched in <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 and fully fleshed out in the comment titled <tt>Essay on
  Admitting a Model for Apply$ and the Functions that Use It</tt> in the ACL2
  source file @('apply-raw.lisp').</p>

  <p>@('Defwarrant') also proves that @(tsee fn-equal) is a congruence
  relation for each @(':FN') position of @('fn').</p>")
other
(defxdoc delete-assoc
  :parents (alists acl2-built-ins)
  :short "Deprecated version of @(see remove1-assoc)"
  :long "<p>See @(see remove1-assoc).</p>")
other
(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.  It returns @('(mv t
 state)') if deletion succeeds and @('(mv nil state)') otherwise.  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$)")
other
(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 @(see 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>")
other
(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 @(see 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>")
other
(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)
 })")
other
(defxdoc df
  :parents (numbers acl2-built-ins)
  :short "Support for floating-point operations"
  :long "<p>ACL2 supports computation that uses floating-point operations.  The
 basic arithmetic operations (@('+'), @('-'), @('*'), and @('/')) in Common
 Lisp can be much faster when applied to floating-point numbers than to
 rational numbers.  Moreover, the floating-point operations include
 transcendental operations such as the sine function.</p>

 <p>All floating-point computations performed by Common Lisp for ACL2 use
 <i>double-floats</i>, that is, double-precision floating-point numbers.
 Computation with other precisions (including single-precision) is not
 supported by ACL2.</p>

 <p>Note: ACL2 novices are advised to skip this topic and program with ordinary
 ACL2 rationals rather than taking advantage of ACL2 support for floating-point
 operations.  The syntactic restrictions described below are somewhat like
 those for single-threaded objects, known as @(see stobj)s, so although
 familiarity with stobjs is not assumed, that familiarity may be helpful for
 understanding ACL2 support for floating-point computations.  (But for
 expressions denoting floating-point computations, unlike those involving
 stobjs, there is no restriction to single instances and there are no
 destructive operations.)</p>

 <p>This topic is organized as follows.  The Introduction may suffice for those
 eager to start playing with ACL2's version of floating-point operations.  The
 second section presents challenges for supporting floating-point operations in
 ACL2, and the third section outlines how ACL2 addresses those challenges.  A
 key enabler for ACL2 support of floating-point operations is how it restricts
 their use syntactically, and this is discussed in Section 4.  Section 5
 discusses guards.  Section 6 documents the built-in ACL2 functions and macros
 that involve floating-point operations.  Section 7 makes some remarks on
 performance.  Finally, Section 8 covers more aspects of ACL2 support for
 floating-point operations by presenting highlights of a substantial file of
 relevant examples: the @(see community-book),
 @('books/demos/floating-point-input.lsp').  We conclude in Section 9 with
 remarks for system programmers.</p>

 <p>This topic is written for ACL2 users.  Implementation-level remarks for
 developers may be found in a comment in the ACL2 sources entitled &ldquo;Essay
 on Support for Floating-point (double-float, df) Operations in
 ACL2&rdquo;.</p>

 <h3>Section 1: Introduction</h3>

 <p>ACL2 differs from Common Lisp by imposing syntactic restrictions on
 expressions that represent floating-point computations, to ensure that these
 computations respect the ACL2 axioms.  Those expressions are called <i>df
 expressions</i>, or <i>dfs</i> for short.  ACL2 may also say that such an
 expression &ldquo;returns a result of shape :DF&rdquo;.</p>

 <p>With those restrictions, ACL2 supports computations with double-precision
 floating-point numbers without adding a floating-point data type to the logic.
 Rather, ACL2 logically treats df expressions as returning rational numbers
 that are <i>representable</i> by floating-point numbers.  For example, there
 is no floating-point number 1.5 in the ACL2 logic; rather, the Common Lisp
 value 1.5 represents the rational number 3/2, which is an ACL2 object, and the
 df expression @('(to-df 3/2)') is provably equal to the constant 3/2 in the
 logic, even though evaluation of @('(to-df 3/2)') in Common Lisp returns the
 double-float 1.5.  Discussion below further explains dfs in ACL2, but for
 starters let's consider the following example.</p>

 @({
 (defun f1 (x)
   (declare (type double-float x))
   (df- x))
 })

 <p>ACL2 admits this definition so that @('f1') is a @(see guard)-verified
 function.  The operation @('df-') is essentially just the negative operation
 (@('-')), except that @('df-') is to be applied only to df expressions; this
 is enforced based on the @('double-float') type declaration.  Let's look at
 what happens when we @(see trace) @('f1'); discussion follows.  In the
 following example, @('f1') is applied to the df expression @('(to-df 3/2)');
 the expression @('(f1 3/2)') would be illegal for top-level evaluation
 because, as noted above, @('f1') expects a df expression, </p>

 @({
 ACL2 !>(trace$ f1 to-df)
 ((F1) (TO-DF))
 ACL2 !>(f1 (to-df 3/2))
 1> (ACL2_*1*_ACL2::TO-DF 3/2)
 <1 (ACL2_*1*_ACL2::TO-DF 3/2)
 1> (ACL2_*1*_ACL2::F1 3/2)
   2> (F1 1.5)
   <2 (F1 -1.5)
 <1 (ACL2_*1*_ACL2::F1 -3/2)
 #d-1.5
 ACL2 !>
 })

 <p>Initially, the function @('to-df') is applied to 3/2.  The result is
 logically still 3/2, not 1.5, because the <i>executable-counterpart</i> for
 @('to-df') returns an ACL2 value, not a Common Lisp value.  (See @(see
 evaluation) for background on executable-counterparts and corresponding raw
 Lisp functions.)  Then 3/2 is passed to the executable-counterpart for
 @('f1').  The @(see guard) of @('f1') holds on 3/2 (we'll discuss guards
 later), so evaluation passes from the executable-counterpart for @('f1') to
 the raw Lisp function for @('f1') after converting 3/2 to a Common Lisp
 double-precision floating-point number, 1.5.  Then @('df-'), which is
 essentially just @('-') in raw Lisp, is applied to obtain -1.5, which is
 returned by raw-Lisp @('f1').  Then the executable-counterpart for @('f1')
 converts -1.5 to the corresponding ACL2 object, the rational -3/2, which is
 ultimately returned to the top-level loop.</p>

 <p>Remark.  The astute reader may have noticed that the executable-counterpart
 for @('to-df') did not call the raw Lisp function for @('to-df').  That is
 because @('to-df') is actually a macro in raw Lisp.</p>

 <h3>Section 2: Challenges for supporting floating-point operations in
 ACL2</h3>

 <p>In this section we motivate ACL2 restrictions pertaining to floating-point
 numbers, which are addressed in the section after this one.</p>

 <p>We start with examples that show why ACL2 cannot allow some common
 operations to be applied to floating-point numbers.  We illustrate using
 computations in raw Lisp; this is relevant since, as noted above, raw-Lisp
 computation supports @(see evaluation) of @(see guard)-verified code.</p>

 <p><b>Problem #1</b>: Addition isn't associative on floating-point
 numbers.</p>

 <p>We see that immediately with the following raw Lisp examples.</p>

 @({
 ? (+ 0.1 (+ 0.2 0.3))
 0.6
 ? (+ (+ 0.1 0.2) 0.3)
 0.6000000000000001
 ?
 })

 <p>Yet ACL2 has the following axiom.</p>

 @(def associativity-of-+)

 <p>So we can't simply apply @('+') to floating-point numbers in ACL2, because
 @(see guard)-verified code leads to raw Lisp computations that would violate
 this axiom.</p>

 <p><b>Problem #2</b>: Functions @('EQUAL') and @('=') are logically the same
 in ACL2 but not in raw Lisp.</p>

 <p>The following succeeds.</p>

 @({
 (thm (equal (equal x y)
             (= x y)))
 })

 <p>Yet the following log shows that raw Lisp can violate that property if we
 allow double-floats.  (In Common Lisp, @('=') compares numeric values while
 @('EQUAL') distinguishes between rationals and floats and even between
 floating-point numbers 0.0 and -0.0.)</p>

 @({
 ? (equal 1 1.0)
 NIL
 ? (= 1 1.0)
 T
 ? (equal 0.0 (- 0.0))
 NIL
 ? (= 0.0 (- 0.0))
 T
 ?
 })

 <h3>Section 3: How the challenges are addressed</h3>

 <p>The following three principles guide support for floating-point
 computations in ACL2.</p>

 <ul>

 <li>(A) Treat floating-point values as rationals.</li>

 <li>(B) Put syntactic limitations on floating-point operations.</li>

 <li>(C) Use @(see partial-encapsulate) to axiomatize floating-point operations
 while supporting evaluation.</li>

 </ul>

 <p>Let's look at these in turn.</p>

 <p><b>(A) Treat floating-point values as rationals.</b></p>

 <p>The ACL2 logic does not include floating-point numbers.  Rather, certain
 rational numbers can be <i>represented by</i> double-precision floating-point
 numbers, known as double-floats, during computations.  We can say that a
 double-float <i>represents</i> a corresponding rational number.  Certain
 expressions denote such <i>representable</i> rational numbers.  Those are
 called <i>df expressions</i> and we say more about them in our discussion of
 (B), below.</p>

 <p>The predicate @('dfp') recognizes those rational numbers that have a
 floating-point representation.  We do not review floating-point numbers here,
 other than to note that a floating-point number is equal to a binary
 significand between 1 and 2 times 2 to a power, such as as @('1.01100 *
 2^30').  For example, 1/4 is representable but 1/3 is not.</p>

 @({
 ACL2 !>(dfp 1/4) ; represented by the double-float, 0.25d0
 T
 ACL2 !>(dfp 1/3) ; not represented by a double-float
 NIL
 ACL2 !>
 })

 <p>ACL2 provides @('#d') notation (see @(see sharp-d-reader)) as a way to read
 floating-point notation as a representable rational, illustrated as
 follows.</p>

 @({
 ACL2 !>#d0.25
 1/4
 ACL2 !>#d3.5
 7/2
 ACL2 !>#d3.1
 6980579422424269/2251799813685248
 ACL2 !>:q

 Exiting the ACL2 read-eval-print loop.  To re-enter, execute (LP).
 ? (= 3.1 6980579422424269/2251799813685248)
 T
 ?
 })

 <p>Although ACL2 simulates floating-point values with rationals, we see below
 how raw Lisp computation can actually use floating-point arithmetic on
 double-precision floating-point numbers.</p>

 <p><b>(B) Put syntactic limitations on floating-point operations.</b></p>

 <p>Here we briefly discuss syntactic restrictions based on the notion
 mentioned above of <i>df expression</i>, or <i>df</i> for short.  A more
 complete discussion is in the section below on Syntactic Restrictions.  With
 those restrictions, ACL2 supports computations with double-precision
 floating-point numbers without adding a floating-point data type to the logic.
 Informally, a df expression is one that computes in raw Lisp to a
 double-float.</p>

 <p>Let us return to the following example.  It uses @('df-'), which is the
 negative operation on dfs; that is, @('(df- x)') is analogous to @('(- x)'),
 but @('df-') operates on a df and returns a df.</p>

 @({
 ACL2 !>(defun f1 (x)
          (declare (type double-float x))
          (df- x))

 Since F1 is non-recursive, its admission is trivial.  We observe that
 the type of F1 is described by the theorem (RATIONALP (F1 X)).  We
 used the :type-prescription rule BINARY-DF+.

 (F1 :DF) => :DF.

 Computing the guard conjecture for F1....

 The guard conjecture for F1 is trivial to prove.  F1 is compliant with
 Common Lisp.

 Summary
 Form:  ( DEFUN F1 ...)
 Rules: ((:TYPE-PRESCRIPTION BINARY-DF+))
 Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
  F1
 ACL2 !>
 })

 <p>Notice the signature shown above for @('f1'):</p>

 @({
 (F1 :DF) => :DF
 })

 <p>This means that the input of @('f1') must be a df expression and @('f1')
 returns a df expression.  ACL2 determines that the input must be a df by
 virtue of the declaration, @('(type double-float x)').  Calls of @('f1') are
 determined to be dfs because the body of @('f1'), @('(df- x)'), is a df.  One
 can say that ACL2 engages in a limited form of strong typing to identify
 certain inputs and outputs of a function symbol as dfs.  Those familiar with
 @(see stobj)s may notice some similarity to the syntactic restrictions on
 stobjs.</p>

 <p>The following example illustrates the requirement that the input of @('f1')
 be a df.</p>

 @({
 ACL2 !>(f1 3)


 ACL2 Error [Translate] in TOP-LEVEL:  The form 3 represents an ordinary
 object, but it is being used where a form representing a :DF was expected.
 See :DOC df.  Note:  this error occurred in the context (F1 3).

 ACL2 !>
 })

 <p>That error can be avoided by converting the input (a rational constant) to
 a suitable df using the primitive, @('to-df') (discussed later).</p>

 @({
 ACL2 !>(f1 (to-df 3))
 #d-3.0
 ACL2 !>
 })

 <p>Notice that the result is displayed using @('#d') notation.  But remember
 that there are no actual floating-point objects in ACL2; @('f1') returns a
 rational logically, namely -3.  However, since the input expression is a df,
 ACL2 prints the evaluation result using @('#d') notation.  (This is analogous
 to the special printing of @('<state>') when the ACL2 state is returned, and
 similarly for user-defined stobjs.)  To see that the logical value returned is
 truly 3, note that the following event is admitted by ACL2:
 @('(thm (equal (f1 (to-df 3)) -3))').</p>

 <p>The tracking of dfs avoids Problem #1 above, that addition isn't
 associative on floating-point numbers.  That's because ACL2 does not allow
 @('+') to be applied to a df, as illustrated by the following example, which
 complains that the @('+') operation is being supplied a df, namely the call of
 @('f1').  The notion &ldquo;a result of shape :DF&rdquo; is synonymous with
 &ldquo;df&rdquo;.</p>

 @({
 ACL2 !>(+ 5 (f1 (to-df 3)))


 ACL2 Error [Translate] in TOP-LEVEL:  It is illegal to invoke F1 here
 because of a signature mismatch.  This function call returns a result
 of shape :DF where a result of shape * is required.  Note:  this error
 occurred in the context (F1 (TO-DF 3)).

 ACL2 !>
 })

 <p>There is however an operation @('df+') that can be applied to @(':DF')
 expressions.</p>

 @({
 ACL2 !>(df+ (to-df 5) (f1 (to-df 3)))
 #d2.0
 ACL2 !>
 })

 <p>In fact @('df+') automatically converts its arguments satisfying @('dfp')
 to be dfs, so the following is also legal since @('5') is converted to
 @('(to-df 5)').</p>

 @({
 ACL2 !>(df+ 5 (f1 (to-df 3)))
 #d2.0
 ACL2 !>
 })

 <p>But @('df+') is not associative; the following fails, as it should.</p>

 @({
 (thm ; FAILS!
  (implies (and (dfp x) (dfp y) (dfp z))
           (equal (df+ (df+ x y) z)
                  (df+ x (df+ y z)))))
 })

 <p>We return now to Problem #2, that the functions @('EQUAL') and @('=') are
 logically the same in ACL2 but not in raw Lisp, as seen by evaluation in raw
 Lisp, where @('(equal 1 1.0)') evaluates to @('nil') but @('(= 1 1.0)')
 evaluates to @('t').  This problem is avoided by our syntactic tracking of df
 expressions.  The following example shows that @('equal') cannot be called on
 a df expression.</p>

 @({
 ACL2 !>(equal 1 (to-df 1))


 ACL2 Error [Translate] in TOP-LEVEL:  It is illegal to invoke TO-DF
 here because of a signature mismatch.  This function call returns a
 result of shape :DF where a result of shape * is required.  Note:
 this error occurred in the context (TO-DF 1).

 ACL2 !>
 })

 <p>One cannot directly test equality of a non-df expression with a df
 expression, but one can compare equality of two df expressions, as the
 following example illustrates.  (This example also illustrates that addition
 is commutative on dfs; we will return elsewhere to this point.)</p>

 @({
 ACL2 !>(df= (df+ #d1.2 #d3.4) (df+ #d3.4 #d1.2))
 T
 ACL2 !>
 })

 <p><b>(C) Use @(see partial-encapsulate) to axiomatize floating-point
 operations while supporting evaluation.</b></p>

 <p>Next we consider how ACL2 introduces the <i>df primitives</i>, that is,
 built-in functions and macros that take or return a df.  Their calls may be
 executed by calling corresponding Common Lisp functions.  But axiomatizing
 these primitives presents a challenge since the Common Lisp language doesn't
 quite tie down the values returned by floating-point operations.  Here is a <a
 href='http://www.lispworks.com/documentation/lw71/CLHS/Body/v_featur.htm'>relevant
 quote from the Common Lisp HyperSpec</a> about the presence of a raw Lisp
 &ldquo;feature&rdquo;, @(':ieee-floating-point').</p>

 <blockquote>
 If present, indicates that the implementation purports to conform to the
 requirements of IEEE Standard for Binary Floating-Point Arithmetic.
 </blockquote>

 <p>ACL2 checks at build time that this feature is present.  However, that IEEE
 standard specifies results of operations with respect to a <i>rounding
 mode</i>.  Probably most or all Common Lisp implementations use <i>round to
 nearest even</i> as their rounding mode, but this is not guaranteed.  We work
 around this problem to some extent by introducing a constrained rounding
 function, @('df-round'), and using it to define the rational function
 primitives: addition (@('df+')), subtraction (@('df-')), multiplication
 (@('df*')), and division (@('df/')).  Transcendental functions, such as the
 sine function, are not as straightforward to define in terms of rounding.
 Although the sine function, for example, might be defined by rounding a
 sufficiently large Taylor approximation, transcendental functions are
 constrained with minimal axioms (at least for now); for example, the sine
 function is implemented by the constrained function, @('df-sin').  Over time
 some of those constraints may be strengthened, or they may even be replaced by
 definitions in terms of @('df-round').</p>

 <p>Even though the df primitives are constrained (except for the rational
 primitive functions, which are defined in terms of the constrained function
 @('df-round')), ACL2 can evaluate their calls, even during proofs.  This is
 arranged by introducing them with @(tsee partial-encapsulate), which allows
 some of the constraints to be implicit; see @(tsee partial-encapsulate).  The
 implicit constraints are based on computation; for example, when ACL2 admits
 the event @('(thm (equal (df-sin 0) 0))'), an implicit constraint guarantees
 @('(equal (df-sin 0) 0)').  There are also explicit constraints, which for
 example allow ACL2 to prove @('(dfp (df-sin x))').  We do not explain further
 here, but the interested reader is welcome to examine relevant comments in the
 ACL2 source code, for example in the @('partial-encapsulate') event that
 introduces @('df-round') in ACL2 source file @('float-a.lisp').</p>

 <p>ACL2 arranges for the host Lisp to evaluate calls of df primitives in @(see
 guard)-verified) and @(':')@(see program)-mode code.  For example, such
 evaluation of a @('df-sin') call leads to a call of @('sin') in Common Lisp.
 The following log illustrates this point and is discussed below.</p>

 @({
 ACL2 !>(defun f2 (x)
          (declare (type double-float x))
          (df-sin x))

 Since F2 is non-recursive, its admission is trivial.  We observe that
 the type of F2 is described by the theorem (RATIONALP (F2 X)).  We
 used the :type-prescription rule RATIONALP-DF-SIN-FN.

 (F2 :DF) => :DF.

 Computing the guard conjecture for F2....

 The guard conjecture for F2 is trivial to prove.  F2 is compliant with
 Common Lisp.

 Summary
 Form:  ( DEFUN F2 ...)
 Rules: ((:TYPE-PRESCRIPTION RATIONALP-DF-SIN-FN))
 Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.00)
  F2
 ACL2 !>(trace$ f2)
  ((F2))
 ACL2 !>(trace! (sin :native t))

 TTAG NOTE: Adding ttag :TRACE! from the top level loop.
 ACL2 !>(f2 (df/ (df-pi) 2))
 1> (ACL2_*1*_ACL2::F2 884279719003555/562949953421312)
   2> (F2 1.5707963267948966)
     3> (SIN 1.5707963267948966)
     <3 (SIN 1.0)
   <2 (F2 1.0)
 <1 (ACL2_*1*_ACL2::F2 1)
 #d1.0
 ACL2 !>
 })

 <p>We see at &ldquo;@('1>')&rdquo; that evaluation arranged to pass
 a (representable) rational number (roughly, &pi;/2) to the
 executable-counterpart for @('f2') (again, for relevant background see @(see
 evaluation)).  But at &ldquo;@('2>')&rdquo;, where evaluation was passed to
 the raw Lisp function for @('f2'), that rational value was converted to the
 corresponding double-float value, which raw Lisp evaluation passed to the
 Common Lisp function @('sin'), at &ldquo;@('3>')&rdquo;.  Common Lisp then
 returned 1.0 for the raw Lisp applications of @('sin') and @('f2'), so that
 finally, the executable-counterpart for @('f2') returned the rational number,
 1.  That value was displayed using @('#d') notation because a call of @('f2')
 is a df.</p>

 <p>Since rounding (to nearest even, in particular) is not tied down by the
 Common Lisp language, different host Lisp implementations may give different
 results.  This leads us to the following point of emphasis.</p>

 <blockquote>
 When a collection of books is certified (see @(see certify-book)), the same
 environment &mdash; in particular the Lisp implementation and operating system
 &mdash; should be used for all of these books, even those included during
 certification.
 </blockquote>

 <p>Otherwise there is a soundness issue.  One might prove, say,
 @('(equal (df-sin 1) A)') and @('(equal (df-sin 1) B)') for distinct (but
 close by) numeric values @('A') and @('B') in two different books, certified
 with ACL2 executables built on different Lisps, and then include those two
 books to prove a contradiction.</p>

 <h3>Section 4: Syntactic Restrictions</h3>

 <p>We now present more details on the syntactic restrictions pertaining to df
 expressions (dfs).  Our discussion is still informal but it should suffice for
 the successful use of dfs in ACL2.  (Optional technical note for those familiar
 with ACL2 source function @('translate11'): a df is an expression whose
 translation is made with stobjs-out equal to @('(:DF)'), and the arguments of
 a function call are those in a @(':DF') position with respect to that function
 symbol's stobjs-in.)</p>

 <p>These syntactic restrictions are not applied in theorem and non-executable
 contexts, in particular not within @(see defthm), @(see thm), and @(tsee
 defun-nx) events and not within a call of @(tsee non-exec).  Below we focus on
 restrictions for a @(tsee defun) event, including its body, guard, and
 measure; but these restrictions also apply to @(tsee defmacro) events, @(tsee
 defconst) events, and top-level evaluation.</p>

 <p>Certain variables may be specified as dfs at the top level in the case of
 @('defun') events but not in other cases.  For a @('defun') event, the
 <i>declared dfs</i> consist of all variables @('vi') listed either in a @(tsee
 declare) form @('(type double-float v1 ... vk)') or an @(tsee xargs)
 declaration @(':dfs (v1 ... vk)').  If @('k') is @('1') then one may write
 @(':dfs v1') to abbreviate @(':dfs (v1)').  These declared dfs are the
 <i>known df variables</i> at the top level of the user-supplied body, guard,
 and measure of @('f').  The rules below indicate, for a set @('V') of
 known df variables, when an expression is a df with respect to @('V'); and
 these rules also speak to legality of certain expressions.</p>

 <p>Before presenting those rules, we extend the notion of a df
 expression (again, df for short) to that of a <i>df{i}
 expression</i> (<i>df{i}</i> for short).  Such an expression is one that
 returns multiple values when the ith value is to be considered a df.  For
 example, the expression @('(mv (to-df x) (df- y) 17)') is a df{0} expression
 and a df{1} expression but not a df{2} expression.  Note that an expression
 that returns a single value might or might not be a df expression, but it is
 never a df{i} expression for any i; and similarly, an expression that returns
 multiple values maybe a df{i} expression for various i but it is never a df
 expression.</p>

 <p>Here are the rules promised above.  They are not complete; for example,
 they do not cover @(tsee stobj-let) expressions.  But those and other cases
 should present no surprises in practice.  Let @('u') be a user-supplied
 term (that is, an <i>untranslated</i> term; see @(see term)).</p>

 <ul>

 <li>If @('u') is a variable, then @('u') is a df with respect to @('V') if and
 only if it is in @('V').</li>

 <li>If @('u') is a constant symbol then it is not a df (with respect to any
 set).</li>

 <li>If @('u') is a @(tsee lambda) expression, then @('u') is a df with respect
 to @('V') if and only if the corresponding @(tsee let) expression is a df with
 respect to @('V').</li>

 <li>If @('u') is a macro call @('(m t1 ... tn)'), then @('u') is a df with
 respect to @('V') if and only if the single-step macroexpansion of @('u') is a
 df with respect to @('V').</li>

 <li>Suppose @('u') is the term @('(f t1 ... tn)') where @('f') is a function
 symbol.  It is required that @('ti') is a df with respect to @('V') if and
 only if the @('i')th formal of @('f') is a declared df of @('f').  An
 exception to that requirement is when @('f') is @('dfp'), in which case the
 only restriction on @('t1') is that it is not a stobj name.  If @('f') returns
 a single value then @('u') is a df (respectively, df{i}) with respect to
 @('V') if and only if the body of @('f') is a df (respectively, df{i}) with
 respect to @('V').</li>

 <li>Consider @('(let ((x1 e1) ... (xk ek)) dcl1 ... dclm body)').  The rules
 apply to each @('ei') with respect to @('V'), but for @('body') the rules
 apply with respect to the following new set of known dfs.  First, remove all
 @('xi') from @('V') except when @('xi') is declared as a df in one of the
 @('dcli') with a @('double-float') type declaration.  For any @('xi') not so
 declared, ACL2 guesses whether or not @('ei') is a df with respect to @('V').
 If the guess is &ldquo;yes&rdquo; then add @('xi') as a known df, and if the
 guess is &ldquo;no&rdquo; then do not add it.  Otherwise, the guess fails to
 yield an answer, in which case ACL2 can try both ways: first it attempts to
 treat (technically, translate) @('ei') as a non-df and, if that fails, it
 treats @('ei') as a df.  (However, the guess almost always works; in
 particular, for a function call it just looks up the function's signature,
 except for a recursive call of a function being defined.)</li>

 <li>For @('(mv-let (x1 ... xk) mv-expr dcl1 ... dclm body)'), the rules apply
 to @('mv-expr') and to @('body'), but for @('body') the known dfs are modified
 as follows.  ACL2 attempts to determine those i &le; k for which @('mv-expr')
 is a df{i} expression.  (Optional technical note for those familiar with ACL2
 source function @('translate11'): ACL2 attempts to determine suitable
 stobjs-out for translation of @('mv-expr').)  Then to obtain the known dfs for
 @('body'), each @('xi') is initially removed from @('V') except for those
 @(see declare)d in some @('dcli') as having type @('double-float'), and then
 those @('xi') for which @('mv-expr') is a df{i} expression are added back as
 known dfs for translation of @('body').</li>

 </ul>

 <p>Note that ACL2 features that naturally traffic in ordinary ACL2 values may
 disallow uses of df expressions (much as they disallow uses of @(see stobj)s).
 Here are a few examples.</p>

 <ul>

 <li>A @(see table) guard must return an ordinary value, not a df.</li>

 <li>A @(see clause-processor) must return an ordinary value (and perhaps
 stobjs in the multiple-values case; see @(see clause-processor)).</li>

 <li>A @(see theory) expression, as well as the argument of @(tsee defconst),
 @(tsee defpkg), @(tsee syntaxp), or @(tsee bind-free), must return an ordinary
 value, not a df.</li>

 </ul>

 <h3>Section 5: Guards</h3>

 <p>When a @(tsee defun) event defines a function, the @(see guard) for that
 function asserts that @('dfp') holds for each declared df.  Here's an
 example</p>

 @({
 (defun df-10/x (x)
   (declare (xargs :guard (not (df= 0 x))
                   :dfs x))
   (df/ 10 x))
 })

 <p>The generated guard is @('(and (dfp x) (not (df= 0 x)))').  Note that
 @('(dfp x)') precedes @('(not (df= 0 x))'): the conjuncts generated from the
 @(':dfs') always precede those that come from @(':guard') specifications.</p>

 <p>Instead of specifying declared dfs using @(':dfs') @(tsee xargs), a better
 approach (see Section 7: Remarks on performance) is to use @('double-float')
 @(tsee type) declarations.  Here's a variant of the example above that uses
 this approach; it too is admitted by ACL2.</p>

 @({
 (defun df-10/x (x)
   (declare (xargs :guard (not (df= 0 x)))
            (type double-float x))
   (df/ 10 x))
 })

 <p>Technical remark (feel free to skip it).  There is a subtlety here.  Unlike
 @(':dfs') specifications, any @(see type) declarations are conjoined with
 @(':guard') specifications in the order of appearance of each.  (This is a
 general aspect of ACL2, not specific to @('double-float') types.)  So in the
 example above, the guard is essentially @('(and (not (df= 0 x)) (dfp x))').
 It may be surprising that @('(df= 0 x)') can itself be guard-verified without
 the assumption of @('(dfp x)').  The reason is that ACL2 figures out that
 @('x') is a declared df, and deduces that since this is legal code, we know
 that @('(dfp x)') is true.</p>

 <h3>Section 6: Df primitives</h3>

 <p>This section documents the df primitives, which (again) are those built-in
 functions and macros that take or return a df.  A small number of related
 built-ins are also documented here.  These are divided here into the following
 groups.</p>

 <ul>
 <li>Recognizers and conversion functions</li>
 <li>Basic arithmetic operations</li>
 <li>Other operations</li>
 </ul>

 <p>In each case, we display a function's signature (as in the example of
 @('f2') above) and describe its functionality.  You can of course use
 @(':')@(tsee pe) to see its logical definition.</p>

 <p>But first we discuss a class of convenient macros.</p>

 <p><u>Corresponding df-friendly macros</u></p>

 <p>Before we document the df primitive functions, we describe corresponding
 macros that automatically convert certain constants to df expressions by using
 a @('to-df') wrapper.  We call such a macro the &ldquo;corresponding
 df-friendly macro&rdquo; for the given function.  Below, we show how that
 works for @('binary-df+') and its corresponding df-friendly macro, @('df+').
 The same relationship holds for other df primitive functions and their
 corresponding df-friendly macros.</p>

 <p>Consider the following examples of adding two dfs with the function
 @('binary-df+').</p>

 @({
 ACL2 !>(binary-df+ (to-df 3) (to-df 1/2))
 #d3.5
 ACL2 !>(let ((x (to-df 3))) (binary-df+ x (to-df 1/2)))
 #d3.5
 ACL2 !>
 })

 <p>The arguments to @('binary-df+') must be dfs, so it is illegal to remove
 any call of @('to-df') above.  For example, all of the following cause
 errors.</p>

 <ol>

 <li>@('(binary-df+ 3 1/2)') <i>; 3 and 1/2 are not dfs</i></li>
 <li>@('(let ((x (to-df 3))) (binary-df+ x 1/2))') <i>; 1/2 is not a
 df</i></li>
 <li>@('(let ((x 3)) (binary-df+ x (to-df 1/2)))') <i>; x is not a df</i></li>

 </ol>

 <p>However, @('binary-df+') has a corresponding df-friendly macro, @('df+').
 That macro expands to a call of @('binary-df') with a call of @('to-df')
 wrapped around every constant numeric argument that satisfies @('dfp').  The
 following calls show expansions of @('df+') calls that correspond to calls
 from the first two examples above.</p>

 @({
 ACL2 !>:trans1 (df+ 3 1/2)
  (BINARY-DF+ (TO-DF 3) (TO-DF 1/2))
 ACL2 !>:trans1 (df+ x 1/2)
  (BINARY-DF+ X (TO-DF 1/2))
 ACL2 !>
 })

 <p>So, evaluation succeeds for those two uses of @('df+') in place of
 @('binary-df+').</p>

 @({
 ACL2 !>(df+ 3 1/2)
 #d3.5
 ACL2 !>(let ((x (to-df 3))) (df+ x 1/2))
 #d3.5
 ACL2 !>
 })

 <p>The third example still fails, however, since @('df+') only wraps
 @('to-df') around constants.</p>

 @({
 ACL2 !>(let ((x 3)) (df+ x (to-df 1/2)))


 ACL2 Error [Translate] in TOP-LEVEL:  The form X represents an ordinary
 object, but it is being used where a form representing a :DF was expected.
 See :DOC df.  Note:  this error occurred in the context
 (BINARY-DF+ X (TO-DF 1/2)).

 ACL2 !>
 })

 <p>Note that a constant value is only supplied a @('to-df') wrapper when it
 satisfies @('dfp'), that is, it is a representable rational, as illustrated by
 the following example.</p>

 @({
 ACL2 !>:trans1 (df+ 1/3 1/4)
  (BINARY-DF+ 1/3 (TO-DF 1/4))
 ACL2 !>
 })

 <p>The focus above has been on numeric constants, but symbolic constants that
 start and end with the &lsquo;@('*')&rsquo; character, like @('*c*'), are
 treated somewhat similarly.  Such an argument of a df-friendly macro is given
 a @('to-df') wrapper as well as an assertion that @('dfp') holds.  Suppose for
 example that we submit the following two events.</p>

 @({
 (defconst *good* 1/4) ; 1/4 satisfies dfp.
 (defconst *bad* 1/3)  ; 1/3 does not satisfy dfp.
 })

 <p>Here is how those arguments are treated when supplied to a df-friendly
 macro.</p>

 @({
 ACL2 !>:trans1 (df+ *good* *bad*)
  (BINARY-DF+ (LET ((C *GOOD*))
                (ASSERT$ (DFP C) (TO-DF C)))
              (LET ((C *BAD*))
                (ASSERT$ (DFP C) (TO-DF C))))
 ACL2 !>
 })

 <p>Indeed, evaluation of @('(df+ *good* *bad*)') results in an assertion
 failure.</p>

 @({
 HARD ACL2 ERROR in ASSERT$:  Assertion failed:
 (ASSERT$ (DFP C) (TO-DF C))
 })

 <p>But logically, @(tsee assert$) returns its second argument, so ACL2 can
 prove the following.</p>

 @({
 (equal (df+ *good* *bad*)
        (binary-df+ *good* (to-df *bad*)))
 })

 <p><u>Recognizers and conversion functions</u></p>

 <p>@('(from-df :DF) => *')<br/>
 Converts a df to a numerically equivalent ordinary value.</p>

 <p>@('(to-df *) => :DF')<br/>
 Converts an ordinary value to a nearby df.  This is the identity on any
 rational that is representable by a floating-point number.</p>

 <p>@('(to-dfp *) => *')<br/>
 This is logically the same as @('to-df'), but it returns an ordinary value
 rather than a df.</p>

 <p>@('(dfp {* or :DF}) => *')<br/>
 Recognizes rationals that can be represented by Lisp double-floats; so, always
 true when applied to a df.  The logical definition of @('(dfp x)') is
 @('(and (rationalp x) (= (to-df x) x))').</p>

 <p>@('(df-round *) => *')<br/>
 Constrained, non-executable rounding function, which converts a rational to a
 nearby value that satisfies @('dfp').  It is used in the definitions of the
 basic arithmetic operations.</p>

 <p>@('(df-string :DF) => *')<br/>
 Produces the floating-point representation, as a string, of the given df
 value.  Examples:</p>

 @({
 ACL2 !>(df-string (to-df 1/4))
 "0.25"
 ACL2 !>(df-string (to-df 1/3))
 "0.3333333333333333"
 ACL2 !>
 })

 <p>@('(df-rationalize-fn :DF) => *')<br/>
 Calls the Common Lisp function, @('rationalize'), which the Common Lisp
 HyperSpec says &ldquo;returns a rational that approximates the float to the
 accuracy of the underlying floating-point representation.&rdquo;  The idea is
 to produce a &ldquo;pretty&rdquo; rational that approximates the given df, as
 illustrated by the following example.</p>

 @({
 ACL2 !>(from-df (to-df 1/10))
 3602879701896397/36028797018963968
 ACL2 !>(df-rationalize (to-df 1/10))
 1/10
 ACL2 !>
 })

 <p>@('(rize *) => *')<br/>
 This is a variant of @('df-rationalize') that operates on rationals instead of
 dfs, as shown by the following extension of the example just above.</p>

 @({
 ACL2 !>(rize 3602879701896397/36028797018963968)
 1/10
 ACL2 !>
 })

 <p><u>Basic arithmetic operations</u></p>

 <p>@('(binary-df+ :df :df) => :df')<br/>
 Adds the two given dfs.<br/>
 Corresponding df-friendly macro: @('(df+ x y )')</p>

 <p>@('(binary-df* :df :df) => :df')<br/>
 Multiplies the two given dfs.<br/>
 Corresponding df-friendly macro: @('(df* x y )')</p>

 <p>NOTE: Both @('df+') and @('df*') are binary, unlike @('+') and @('*').  An
 immediate issue is that the failure of associativity could cause a divergence
 with the logical expansion into a right-associated sum or product, for example
 in raw Lisp as follows.</p>

 @({
 ? (+ .1 .2 .3)
 0.6000000000000001
 ? (+ .1 (+ .2 .3))
 0.6
 ?
 })

 <p>@('(binary-df/ :df :df) => :df')<br/>
 Divides the two given dfs, where the second should be non-zero.<br/>
 Corresponding df-friendly macro: @('(df/ x y )')</p>

 <p>@('(unary-df- :df) => :df')<br/>
 Takes the negative of the given df.<br/>
 Corresponding df-friendly macro: @('(df- x)')</p>

 <p>@('(unary-df/ :df) => :df')<br/>
 Takes the reciprocal of the given non-zero df.<br/>
 Corresponding df-friendly macro: @('(df/ x)')</p>

 <p>Also provided is a binary version of the macro @('df-').  The expansion of
 @('(df- term1 term2)') is essentially @('(df+ term1 (df- term2))').</p>

 <p>These functions are all defined by applying @('df-round') to the exact
 mathematical result.  Here are their definitions in the ACL2 logic.</p>

 @(def binary-df+)
 @(def binary-df*)
 @(def binary-df/)
 @(def unary-df-)
 @(def unary-df/)

 <p>We include the following as a basic arithmetic operation (though some may
 argue with that classification).</p>

 <p>@('(df-abs-fn :df) => :df')<br/>
 Return the absolute value of the df input, as a df.<br/>
 Corresponding df-friendly macro: @('(df-abs x)')</p>

 <p><u>Other operations</u></p>

 <p>These are listed alphabetically.  They include the square root function and
 common transcendental functions.  The first two are logarithm functions.</p>

 <p>@('(binary-df-log :df :df) => :df')<br/>
 Takes the log, where the first argument is the base.<br/>
 Corresponding df-friendly macro: @('(df-log x y)')</p>

 <p>@('(unary-df-log :df) => :df')<br/>
 Takes the natural log (log base @('e')) of the given df.<br/>
 Corresponding df-friendly macro: @('(df-log x)')</p>

 <p>The following zero-ary functions return floating-point constants.</p>

 <p>@('(df-pi) => :df')<br/>
 Returns a df approximation to &pi;.<br/>
 The constant @('*df-pi*') is defined to be the corresponding rational:<br/>
 @('(defconst *df-pi* (from-df (df-pi)))').</p>

 <p>@('(df0) => :df')<br/>
 Returns a df logically equal to 0.</p>

 <p>@('(df1) => :df')<br/>
 Returns a df logically equal to 1.</p>

 <p>@('(df-minus-1) => :df')<br/>
 Returns a df logically equal to -1.</p>

 <p>The remaining functions are listed in alphabetic order.  Each has a name of
 the form @('df-NAME-fn') where @('NAME') is the name of a corresponding Common
 Lisp function.  Each takes a df argument except for @('expt'), which takes two
 df arguments, and each returns a df argument.  The guards require not only
 @('dfp') of each argument but the extra conditions as shown below.  Each has a
 corresponding df-friendly macro, @('df-NAME').</p>

 <dl>
 <li>@('(df-acos-fn x)') ; guard extra: @('(df<= (df-abs-fn x) 1)')</li>
 <li>@('(df-acosh-fn x)')</li>
 <li>@('(df-asin-fn x)')</li>
 <li>@('(df-asinh-fn x)')</li>
 <li>@('(df-atan-fn x)')</li>
 <li>@('(df-atanh-fn x)') ; guard extra: @('(df< (df-abs x) 1)')</li>
 <li>@('(df-cos-fn x)')</li>
 <li>@('(df-cosh-fn x)')</li>
 <li>@('(df-exp-fn x)')</li>
 <li>@('(df-expt-fn x y)') ; guard extra: @('(or (df< 0 x) (and (df= 0 x) (df< 0 y)))')</li>
 <li>@('(df-sin-fn x)')</li>
 <li>@('(df-sinh-fn x)')</li>
 <li>@('(df-sqrt-fn x)') ; guard extra: @('(df<= 0 x)')</li>
 <li>@('(df-tan-fn x)') ; guard extra: @('(not (df= (df-cos-fn x) 0))')</li>
 <li>@('(df-tanh-fn x)') ; guard extra: @('(not (df= (df-cosh-fn x) 0))')</li>
 </dl>

 <h3>Section 7: Remarks on performance</h3>

 <p>This section covers just a few aspects of performance pertaining to the use
 of dfs.  Those who use dfs and can provide useful performance tips are
 welcomed to extend this section.</p>

 <p><u>Inlining of df primitives</u></p>

 <p>Suppose we start ACL2 and then submit the following forms, which define
 @('g1') in raw Lisp and provide its assembly code.</p>

 @({
 (defun g1 (x y) (declare (type double-float x y)) (df< x y))
 (disassemble 'g1)
 })

 <p>If we repeat this experiment in a new ACL2 session except that we replace
 @('df<') with @('<'), we get the same assembly code (at least, when using ACL2
 built on CCL or on SBCL as of this writing).  This is good; it shows that
 there is no performance penalty for using @('df<').  To understand why, first
 observe that macroexpansion replaces @('df<') by @('df<-fn'); then observe
 that the ACL2 sources include a @('declaim') form that declares @('df<-fn') to
 be inline.  All the df primitive functions are similarly declared inline
 except for @('to-df'), which we discuss next.  Of course, these inlined raw
 Lisp functions (and macro) cannot generally be @(see trace)d.</p>

 <p><u><tt>To-df</tt></u><u> is a macro in raw Lisp</u></p>

 <p>Although @('to-df') is a function in the ACL2 logic, it is implemented as a
 macro in raw Lisp.  To see how that benefits performance, consider the
 following definition.</p>

 @({
 (defun add3 (x) (declare (type double-float x)) (df+ 3 x))
 })

 <p>We can see the translation of that @('df+') call as follows.</p>

 @({
 ACL2 !>(body 'add3 nil (w state))
 (BINARY-DF+ (TO-DF '3) X)
 ACL2 !>
 })

 <p>Since @('binary-df+') is inlined in raw Lisp (see above), its call above
 essentially equivalent in raw lisp to @('(+ (TO-DF '3) X)').  But it would be
 unfortunate to call to-df at runtime, even if @('to-df') were an inlined
 function.</p>

 <p>However, @('to-df') is a macro that expands away its call on a rational
 argument or quoted rational argument.</p>

 @({
 ? (macroexpand-1 '(TO-DF '3))
 3.0
 T
 ?
 })

 <p>A key performance tip is that a @('defun') form should @(see declare) dfs
 with a type declaration rather than an @('xargs :dfs') declaration.  Here are
 examples.</p>

 <p><u>Type declarations are probably preferred</u></p>

 <p>This observation is not really specific to the use of dfs.  Common Lisp
 compilers can sometimes take advantage of @('type') @(see declaration)s, but
 they never take advantage of @('xargs') declarations (because those are
 ignored by the compiler).  So just as one may get better performance with a
 declaration @('(type (integer 0 *) x)') than with @('(xargs :guard (natp
 x))'), one may get better performance with (declare (type double-float x))
 than with @('(xargs :dfs x)').</p>

 <h3>Section 8: More examples</h3>

 <p>This section, which forms the remainder of this topic, is a synopsis of
 @(see community-books) file @('books/demos/floating-point-input.lsp').  It may
 be useful to skip this section and instead read that file; or one could
 consult that file when an example given below needs more explanation, since
 other examples in that file may be clarifying.  Comments in that file may
 suffice to explain what is going on, but if not, then corresponding output
 file @('books/demos/floating-point-log.txt') (generated by the @(see
 run-script) utility) may be worth a look.</p>

 <p>Here are the contents of that file (quoting from a comment near its
 top).</p>

 @({
 ;;; TABLE OF CONTENTS
 ;;; -----------------
 ;;; "Floats" as rationals
 ;;; Overflow and underflow
 ;;; An assertion macro
 ;;; Df-rationalize and rize
 ;;; More on dfp & to-df (recognizer & generator for representables)
 ;;; Fun with pi
 ;;; No support for complex floats
 ;;; Examples with defined functions
 ;;; Examples focused on ec-call
 ;;; We can't prove much
 ;;; Df stobj fields
 ;;; Arrays of double-floats
 ;;; DO loop$ expressions
 ;;; FOR loop$ expressions
 ;;; Stobj-let (nested stobjs)
 ;;; Using apply$ with dfs, including efficiency issues
 ;;; Encapsulate and signatures
 ;;; Memoization
 ;;; Miscellany
 ;;; Check consistency with values produced in raw Lisp
 })

 <p>We now hit some highlights of each of those sections that may not have been
 adequately covered above.  See @('books/demos/floating-point-input.lsp') for
 more details, e.g., the use of either @('E') or @('D') as an exponent
 marker.</p>

 <p><i>;;; "Floats" as rationals</i></p>

 @({
 (assert-event
 ; 31/10 is not representable, but every #d number that is read without
 ; error is representable -- hence the equality below is false.
  (not (equal #d3.1 31/10)))

 (assert-event (equal #d1d50 #d1.0E50)) ; Both are the same rational.

 ; The following are not quite equal because the latter is not representable.
 (assert-event (not (equal #d1d50 (expt 10 50))))

 (assert-event
  (let ((x (to-df #d.1))
        (y (to-df #d.2))
        (z (to-df #d.3)))
    (not (df= (df+ (df+ x y) z)
              (df+ x (df+ y z))))))
 })

 <p><i>;;; Overflow and underflow</i></p>

 @({
 #d1E310 ; Lisp error (overflow)

 #d1E-500 ; 0 (underflow)
 (to-df #d1E-500) ; #d0.0 (underflow)
 })

 <p><i>;;; An assertion macro</i></p>

 <blockquote>
 <p>This section just defines a macro, @('a-e'), which checks that its input is
 true in two ways: by direct evaluation and by proof.</p>
 </blockquote>

 <p><i>;;; Df-rationalize and rize</i></p>

 @({
 (thm (equal (to-df 1/3) ; Rational representation is on next line.
             6004799503160661/18014398509481984))

 (df-rationalize
  (to-df 1/3)) ; result is 1/3

 (rize 1/3) ; 1/3; equivalent to (df-rationalize (to-df 1/3)) above
 })

 <p><i>;;; More on dfp &amp; to-df (recognizer &amp; generator for representables)</i></p>

 @({
 (a-e (equal (dfp 1/4) t)) ; 1/4 is representable
 (a-e (equal (dfp 1/3) nil)) ; 1/3 is not representable
 (a-e ; to-df maps a rational to one that's representable
  (equal (dfp (to-df 1/3)) t))
 (thm (equal (to-df 'abc) 0)) ; default guard-violating behavior
 })

 <p><i>;;; Fun with pi</i></p>

 @({
 (defconst *2pi*
 ; See also df-2pi.  This is a rational approximation to 2*pi.  Note
 ; that *df-pi* is already defined as a rational approximation to pi.
 ; Both *df-pi* and *2pi* are ordinary objects, not dfs; defconst
 ; always creates an ordinary object.
   (* 2 *df-pi*))

 ; Signature shows return of :DF in the following.
 (defun-inline df-2pi ()
 ; See also *2pi*.  Here, however, we return a :df (which is a
 ; double-float in raw Lisp) rather than an ordinary object.  Note that
 ; since (df-pi) is representable, multiplying it by 2 produces a
 ; representable rational as well (since that multiplication keeps the
 ; mantissa and simply doubles the small exponent).
   (df* 2 (df-pi)))

 (a-e
 ; This holds since *df-pi* = (df-pi) and (df-2pi) is just the exact
 ; product by 2 of (df-pi), as noted above.
  (equal *2pi* (from-df (df-2pi))))

 (df-sin (df-2pi)) ; very near 0, but not 0 (floating-point sin is not exact)
 })

 <p><i>;;; No support for complex floats</i></p>

 @({
 (to-df #c(0 1)) ; guard violation (expects a rational)
 })

 <p><i>;;; Examples with defined functions</i></p>

 <blockquote>
 <p>This section of @('books/demos/floating-point-input.lsp') has several
 examples that are worth reading if you have difficulties defining functions
 that traffic in dfs.  In particular, it shows how to use @('THE') (see @(see
 the)) with a @('double-float') @(see type-spec) to assist ACL2 with its syntax
 checking.</p>
 </blockquote>

 <p><i>;;; Examples focused on ec-call</i></p>

 <blockquote>
 <p>The example below shows the need to add a @(':dfs') argument to @(tsee
 ec-call) when the call returns a df.  See this section in
 @('books/demos/floating-point-input.lsp') for additional discussion and
 examples.</p>
 </blockquote>

 @({
 (defun f6 (x)
   (declare (xargs :guard (rationalp x)))
   (ec-call (unary-df- (to-df x))
            :dfs-in '(t)
            :dfs-out '(t)))
 })

 <p><i>;;; We can't prove much</i></p>

 <blockquote>
 <p>This section of @('books/demos/floating-point-input.lsp') gives some
 examples of what can be proved about df operations and what cannot be
 proved.</p>
 </blockquote>

 <p><i>;;; Df stobj fields</i></p>

 @({
 (defstobj st1
   (accum :type double-float :initially 0))

 (assert-event (df= (accum st1) 0))

 (update-accum (to-df 3) st1)

 (assert-event (df= (accum st1) 3))
 })

 <p><i>;;; Arrays of double-floats</i></p>

 @({
 (defstobj st3
 ; Here is an array of double-floats.  The implementation will, as
 ; usual, take into account the array element type (here, double-float)
 ; when reading or writing the array, by generating suitable type
 ; declarations.
 ; NOTE: It may be that code runs faster (but using more space) if the raw Lisp
 ; array is declared to have elements of type t instead of type double-float.
 ; Such a change might be considered in the future.
   (ar :type (array double-float (8)) :initially 0))

 (defun load-ar (i max lst st3)
 ; Update the ar field of st3 with the values in lst, starting at position i.
   [[.. elided here; see books/demos/floating-point-input.lsp ..]])

 (load-ar 0 8 (list 3 0 *df-pi* 3/4 -2/3 5 -6 7) st3)

 (assert-event (and (= (from-df (ari 2 st3)) *df-pi*)
                    (= (from-df (ari 6 st3)) -6)
                    (df= (ari 6 st3) -6)
                    (df< (ari 0 st3) 5)))

 (defthm dfp-nth-arp
 ; a useful lemma
   (implies (and (arp ar)
                 (natp i)
                 (< i (len ar)))
            (dfp (nth i ar))))

 ; We can read dfs and update with dfs.
 (defun scalar-multiply-ar (i mult st3)
   (declare (xargs :stobjs st3
                   :guard (and (natp i) (<= i 8)))
            (type double-float mult))
   (cond ((zp i) st3)
         (t (let* ((i (1- i))
                   (old (ari i st3))
                   (st3 (update-ari i (df* mult old) st3)))
              (declare (type double-float old))
              (scalar-multiply-ar i mult st3)))))

 (defun scalar-multiply-ar-example (st3)
    (declare (xargs :stobjs st3))
    (scalar-multiply-ar 4 (to-df 4) st3))

 (load-ar 0 8 (list 3 0 *df-pi* 3/4 -2/3 5 -6 7) st3)

 (scalar-multiply-ar-example st3)

 (assert-event (and (= (from-df (ari 2 st3)) (* 4 *df-pi*))
                    (= (from-df (ari 6 st3)) -6)
                    (df= (ari 6 st3) -6)
                    (df< (ari 0 st3) 20)))
 })

 <p><i>;;; DO loop$ expressions</i></p>

 <blockquote>
 <p>This section of @('books/demos/floating-point-input.lsp') continues using
 the stobj from the preceding section to show how @('DO') @(tsee loop$)
 expressions can operate on a stobj array.</p>
 </blockquote>

 <p><i>;;; FOR loop$ expressions</i></p>

 @({
 ; The following is illegal, because it is illegal to use a df variable (in this
 ; case, w) in a FOR loop$ expression.  Use DO loop$ expressions instead in such
 ; cases, as illustrated in the preceding section.
 (let ((w (to-df 7)))
   (loop$ for v from 1 to 3
          sum (from-df (df+ w (to-df v)))))
 })

 <p><i>;;; Stobj-let (nested stobjs)</i></p>

 <blockquote>
 <p>This section of @('books/demos/floating-point-input.lsp') shows that the
 @(tsee stobj-let) utility works properly with dfs.</p>
 </blockquote>

 <p><i>;;; Using apply$ with dfs</i></p>

 @({
 ; We see in examples below that apply$ works with df arguments.  This may seem
 ; surprising.  After all, there is a similar prohibition on stobj arguments
 ; because a stobj cannot be put into a list; wouldn't such a prohibition
 ; similarly pertain to df arguments, since they too cannot be put into a list?

 ; However, ACL2 evaluation of apply$ calls takes place by calling *1*
 ; functions, and these tolerate ordinary rational inputs where dfs are
 ; expected.  So apply$ accepts rational arguments where dfs are expected,
 ; provided they satisfy dfp.

 (defun f0 (x)
   (declare (xargs :verify-guards nil)
            (type double-float x))
   (df- x))

 ; This too is redundant (already included above).
 (include-book "projects/apply/top" :dir :system)

 ; "Teach" apply$ about f0:
 (defwarrant f0)

 ; Succeeds, since 1/4 satisfies the guard for f0, (dfp x).
 (assert-event (equal (apply$ 'f0 (list 1/4))
                      -1/4))

 ; Same as above, since the #d quantities are just rationals:
 (assert-event (equal (apply$ 'f0 (list #d0.25))
                      #d-0.25))

 ; Error: guard violation, since (dfp 1/3) is false.
 (apply$ 'f0 (list 1/3))

 ;;; Efficiency issues when using apply$ with dfs</i></p>
 [[.. Examples omitted here; see books/demos/floating-point-input.lsp. ..]]
 })

 <p><i>;;; Encapsulate and signatures</i></p>

 @({
 (encapsulate
   (((f16 *) => :df :formals (x) :guard (rationalp x)))
   (local (defun f16 (x)
            (declare (ignore x))
            (to-df 0))))

 (defstub f19 (:df) => (mv :df :df))
 })

 <p><i>;;; Memoization</i></p>

 @({
 ; Memoization works fine with dfs; the subtleties when memoizing with stobjs
 ; don't apply to dfs.
 })

 <p><i>;;; Miscellany</i></p>

 @({
 ; The following defun-sk is accepted, even though y represents an ordinary
 ; object, because by default the defun-sk function is non-executable.
 (defun-sk f25 (x)
   (declare (xargs :dfs (x)))
   (exists (y) (df< x y)))

 ;;; Memoize-partial works fine with dfs.
 })

 <p><i>;;; Check consistency with values produced in raw Lisp</i></p>

 @({
 ; This section has tests to check that ACL2 evaluation with dfs agrees with
 ; corresponding Common Lisp evaluation on double-floats.
 })

 <h3>Section 9: Remarks for system programmers</h3>

 <p>Probably most ACL2 users should skip this section.  But those who use
 ACL2 system utilities (see for example @(see system-utilities) and @(see
 programming-with-state)) may find some remarks here to be useful.</p>

 <p>The functions @('translate'), @('translate1'), @('translate-cmp'), and
 @('translate1-cmp') all convert a user-level @(see term) to a translated
 term.  Each of these assumes that no free variable of the user-level term is a
 df.  The function @('translate1-cmp+') has an extra argument, @('known-dfs'),
 that is a list of free variables that are to be considered to be dfs.</p>

")
other
(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)")
other
(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)")
other
(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)")
other
(defxdoc disable
  :parents (theories theory-functions)
  :short "Deletes names from current theory"
  :long "@({
  Example:
  (disable fact (:e 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>

 <p>To see the runes currently disabled that are among those created when a
 function symbol @('FN') is introduced, evaluate @('(disabledp 'FN)').</p>")
other
(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>")
other
(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))
 })")
other
(defxdoc disable-ubt
  :parents (history)
  :short "Make it illegal to undo back through the current @(see command)"
  :long "<p>The utility @('disable-ubt') is probably only relevant to those who
 write ACL2-based tools, in particular using @(see wormhole)s.  Its initial
 application (and perhaps still its only application) is to arrange that inside
 the @(see break-rewrite) interactive loop, it is impossible to undo the @(see
 ld-keyword-aliases) supporting the @(see brr-commands).</p>

 @({
 General Forms:

 :disable-ubt
 (disable-ubt)     ; same as above
 (disable-ubt arg) ; same as above if arg is not nil or :disable-ubt
 })

 <p>where @('arg') is evaluated, and if it is supplied and its value is neither
 @('nil') nor @(':disable-ubt'), then its value satisfies @(tsee msgp).  In
 that case, the message is printed after the usual message (except, before
 ``See :DOC disable-ubt'').  The following example illustrates the use of that
 optional message but, what is more important, it illustrates the effect of
 @('disable-ubt'): a @(see command) that executes it cannot be undone.</p>


 @({
 ACL2 !>(disable-ubt (list "Just a demo: ~x0." (cons #0 17)))

 Summary
 Form:  ( DISABLE-UBT ...)
 Rules: NIL
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
  :DISABLE-UBT
 ACL2 !>:ubt :x


 ACL2 Error in :UBT:  Can't undo a :disable-ubt event (at command 1).
 Just a demo: 17.  See :DOC disable-ubt.

 ACL2 !>
 })

 <p>@('Disable-ubt') is similar to @('(reset-prehistory t)'), as both establish
 a barrier to undoing.  However, for history commands such as @(':')@(tsee
 pcb), command numbers are not changed by @('disable-ubt').  Like @(tsee
 reset-prehistory), @('disable-ubt') is never @(see redundant).</p>

")
other
(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>")
other
(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>")
other
(defxdoc dive-into-macros-table
  :parents (proof-builder 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>")
other
(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) (also see
 related utility @(see with-brr-data)) &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-acl2.el') from a suitable directory; see @(see
 emacs).  Otherwise, load into Emacs the file @('monitor.el') from that same
 directory.  (You only need to do that once in your Emacs session.)  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 @(see 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>")
other
(defxdoc do$
  :parents (loop$ do-loop$)
  :short "Definition of @('do$')"
  :long "<p>@('Do$') is the logical function that interprets @('do')
  @('loop$')s.  See @(see do-loop$) for a discussion of @('do$').</p>

  <p>The function takes six arguments but only the first five are
  relevant to its logical value.</p>

  <ul>

  <li>@('measure-fn') &mdash; a @(tsee lambda) object that computes the measure
  that supposedly decreases (under @(tsee l<)) on each iteration of the
  @('do-fn') and is checked after each iteration, </li>

  <li>@('alist') &mdash; an alist that binds the variable symbols used in the
  body and @('finally') clause (if any) to their values,</li>

  <li>@('do-fn') &mdash; a @('lambda') object that computes the results of one
  iteration, where the results are represented by a triple consisting of an
  exit token that indicates where control goes next, the value (if a
  @('return') was executed), and a new @('alist'),</li>

  <li>@('finally-fn')&mdash; a @('lambda') object that computes the value of
  the @('finally') clause, and</li>

  <li>@('values') &mdash; the output signature of the value to be returned if
  the @('measure') fails to decrease.</li>

  </ul>

  @(def do$)

  <p>The last argument is only relevant in the error message printed if the
  @('do$') fails to terminate and that message is not part of the returned
  value.</p>")
other
(defxdoc do-loop$
  :parents (loop$)
  :short "Iteration with @(tsee loop$) using local variables and @(see stobj)s"
  :long "<p>This topic assumes that you have read the introduction to
 @('loop$') expressions in ACL2; see @(see loop$).  Here we give more complete
 documentation on @('DO') @('loop$') expressions.  This discussion is
 partitioned into the following sections</p>

 <ul>
 <li>INFORMAL INTRODUCTION &mdash; examples of @('DO') @('loop$') expressions</li>
 <li>SYNTAX &mdash; detailed discussion of the legal syntax</li>
 <li>SEMANTICS &mdash; detailed discussion of how @('DO') @('loop$') expressions
 are translated into calls of the general-purpose function @(tsee DO$)</li>
 <li>SIGNALING ERRORS &mdash; how @('DO') @('loop$')s can signal errors</li>
 </ul>

 <p>For a discussion of proofs about @('loop$')s, see @(see
 stating-and-proving-lemmas-about-loop$s).</p>

 <p>More examples of @(tsee loop$) expressions, including @('DO') @('loop$')s,
 may be found in @(see community-book) @('projects/apply/loop-tests.lisp').</p>

 <h3>INFORMAL INTRODUCTION</h3>

 <p>The most basic @('DO') @('loop$') expressions have the following form.</p>

 @({
 (loop$ WITH v1 = a1
        ...
        WITH vn = an
        DO body)
 })

 <p><b>A Basic Example</b></p>

 <p>The example @('loop$') expression below initially stores the list @('(a b
 c)') in the variable @('x') and @('nil') in the variable @('y').  Then it
 iterates, repeatedly popping the first element of @('x') onto @('y') until
 @('x') is empty.  Then it returns the final value of @('y').</p>

 @({
 ACL2 !>(loop$ with x = '(a b c)
               with y = nil
               do (cond ((consp x)
                         (progn (setq y (cons (car x) y))
                                (setq x (cdr x))))
                        (t (return y))))
 (C B A)
 ACL2 !>
 })

 <p>This example illustrates the basic operation of @('DO') @('loop$')
 expressions.</p>

 <ul>

 <li>Initially, variables are initialized according to the @('WITH')
 clauses: for each binding @('WITH Vi = Ei'), we say that @('Vi') is a
 <i>@('WITH')-bound variable</i>, and @('Vi') is initially bound to the value
 of @('Ei').

 <ul><li>In this example, @('x') is initially bound to the list @('(a b c)')
 and @('y') is initially bound to @('nil').</li></ul></li>

 <li>Then, the <i>loop body</i> &mdash; i.e., the term after the @('DO')
 keyword &mdash; is repeatedly evaluated.  An update to @('WITH')-bound
 variable @('Vj') occurs whenever an expression @('(setq Vj Ej)') is
 encountered while evaluating the loop body, binding @('Vj') to the value of
 @('Ej') (which may reference the current values of @('WITH')-bound variables).

 <ul><li>In this example, as long is @('x') is a cons, @('y') is assigned to
 @('(cons (car x) y)') and then @('x') is assigned to the @('cdr') of its
 current value.</li></ul></li>

 <li>Ultimately an expression @('(RETURN E)') should be encountered, in which
 case the value of @('E') is returned &mdash; where as before, @('E') may
 reference the current values of @('WITH')-bound variables.

 <ul><li>In this example, when @('x') is not a cons (and hence is, in fact,
 @('nil')), the current value of @('y') is returned as the value of the
 @('loop$') expression.  By this point each element of the initial value of
 @('x') has been pushed onto @('y'), so the value @('(c b a)') is
 returned.</li></ul></li>

 </ul>

 <p>Note that @('progn') is permitted as shown, to connect a sequence of
 expressions.  Indeed, that is how more than one assignment is accomplished;
 unlike Common Lisp, the @('DO') keyword is followed by exactly one expression,
 so @('DO expr1 expr2') is illegal in ACL2 but @('DO (progn expr1 expr2)') is
 fine.</p>

 <p>Also note that the @('WITH')-bound variables are initialized sequentially:
 later bindings may reference values of earlier ones, for example as
 follows.</p>

 @({
 ACL2 !>(loop$ with x = (* 3 4) with y = (* 10 x) do (return (list y)))
 (120)
 ACL2 !>
 })

 <p>See @(see lp-section-14) of the @('Loop$') Primer for some exercises in
 writing and executing @('DO') @('loop$')s (with answers in a Community Book).
 But remember to come back here when you get to the end of that section.</p>

 <p><b>Parallel Assignment Using @('Mv-setq')</b></p>

 <p>ACL2 also supports parallel assignment to two or more variables, using
 @('mv-setq').  The following is equivalent to the example immediately
 above.</p>

 @({
 ACL2 !>(loop$ with x = '(a b c)
                with y = nil
                do (cond ((consp x)
                          (mv-setq (x y)
                                   (mv (cdr x) (cons (car x) y))))
                         (t (return y))))
 (C B A)
 ACL2 !>
 })

 <p>Thus, the first argument of an @('mv-setq') call is not evaluated, and is a
 list of distinct variables of length at least 2.  The second argument is any
 expression that returns multiple values consistent with the first argument
 &mdash; ``consistent'' in the sense that the number of values returned equals
 the number of variables in the first argument and stobjs must match up.  Thus,
 the rules for @('(mv-setq vars expr)') are the same as for @('(mv-let vars
 expr ...)').</p>

 <p><b>The @('FINALLY') Clause</b></p>

 <p>We have seen the @('loop$') keywords @('WITH') and @('DO').  A third
 @('loop$') keyword, @('FINALLY'), is also supported.  Here is a variant of the
 preceding example that illustrates the use of @('FINALLY').  The iteration
 stops with the @('(loop-finish)') form this time, rather than with a call of
 @('return').  Execution of @('(loop-finish)') passes control to the
 @('FINALLY') clause, which is executed just like the @('DO') body but with a
 single pass, thus determining the value of the @('loop$') &mdash; in this
 example, returning the final value of @('y').</p>

 @({
 ACL2 !>(loop$ with x = '(a b c)
               with y = nil
               do (cond ((consp x)
                         (progn (setq y (cons (car x) y))
                                (setq x (cdr x))))
                        (t (loop-finish)))
               finally (return y))
 (C B A)
 ACL2 !>
 })

 <p>This example illustrates that @('(loop-finish)') terminates the iteration,
 passing control to the @('FINALLY') clause if there is one.  The @('FINALLY')
 clause is evaluated under the current bindings of the @('WITH')-bound
 variables, just as a @('DO') body is executed (but with a single pass rather
 than iteration).</p>

 <p>The value returned by a @('DO') @('loop$') expression is @('nil') when no
 @('return') expression is evaluated (or more generally, a suitable value
 consistent with the @(':VALUES') keyword discussed below).  Here is an
 example, which illustrates an error that may be easy to commit.</p>

 @({
 ACL2 !>(loop$ with x = '(a b c)
               with y = nil
               do (cond ((consp x)
                         (progn (setq y (cons (car x) y))
                                (setq x (cdr x))))
                        (t (loop-finish)))
               finally (length y))
 NIL
 ACL2 !>
 })

 <p>Presumably the intention was to return the length of @('y'), which in this
 case would be 3.  But then the @('FINALLY') clause should have been
 @('(return (length y))').</p>

 <p><b>The @(':VALUES') Keyword</b></p>

 <p>The @(':VALUES') keyword is necessary for a @('loop$') expression that
 returns a @(see double-float), a @(see stobj) or @(see multiple-value)s.  When
 the @(':VALUES') keyword is used, the syntax is @(':VALUES (v0 ... vk)'),
 where each @('vi') is either @('nil'), @(':df'), or a stobj
 name. @(':VALUES (nil)') denotes return of a single ordinary value;
 @(':VALUES (s)') denotes return of a single value that is a stobj named
 @('s'); and @(':VALUES (v0 ... vk)') for k &gt; 0 denotes return of k+1
 values, where @('vi') is @('nil') if the ith returned value is an ordinary
 value, @(':DF') if the ith returned value is a double-float, and otherwise
 @('vi') is the name of the stobj returned as the ith value.  You may
 recognize (v0 ... vk) as an output signature.  If the measure supplied to
 @('do$') fails to decrease on an iteration, an error is caused and the output
 signature is used compute a ``default value,'' which is generally a list of
 k+1 objects (but is a single object when k is 0).  The ith object in the
 default value is @('nil') if @('vi') is @('nil'), is @('#d0.0') if @('vi') is
 @(':DF'), and is the last latched value of the named stobj otherwise. No stobj
 name may be duplicated, and @(':VALUES') must appear between the @('DO') loop
 keyword and the @('DO') body.  Let's look at an example.</p>

 <p>Below we introduce a @(see stobj) and add a @(see warrant) for its accessor
 and updater.  Warrants are necessary for functions called in @('DO') bodies
 and @('FINALLY') clauses in order for those forms to be evaluated.  See @(see
 loop$) for a discussion of the necessity of such warrants.  The two @('loop$')
 expressions are similar in nature to those above, first without and then with
 a @('FINALLY') clause; also see the discussion below.  All forms below
 complete successfully.</p>

 @({
 (include-book "projects/apply/top" :dir :system)
 (defstobj st fld)
 (defwarrant fld)
 (defwarrant update-fld)
 ; Check that (fld st) is currently nil.
 (assert-event (equal (fld st) nil))
 (loop$ with x = '(1 2 3)
        do
        :values (st)
        (cond ((endp x)
               (return st))
              (t (mv-setq (st x)
                          (let ((st (update-fld (cons (car x)
                                                      (fld st))
                                                st)))
                            (mv st (cdr x)))))))
 (assert-event (equal (fld st) '(3 2 1)))
 (update-fld nil st)
 (assert-event (equal (fld st) nil))
 (loop$ with x = '(1 2 3)
        do
        :values (st)
        (cond ((endp x)
               (loop-finish))
              (t (progn (setq st
                              (update-fld (cons (car x)
                                                (fld st))
                                          st))
                        (setq x (cdr x)))))
        finally (return st))
 (assert-event (equal (fld st) '(3 2 1)))
 })

 <p>These loops are similar to those we saw earlier, but this time, when we pop
 values from @('x') they go into a stobj.  Since we return that stobj, @('st'),
 the @(':VALUES') is @('(st)').  The fifth argument of the call of @('do$')
 generated from these @('loop$')s is @(''(st)').  One might expect @(':VALUES')
 to be @('st') instead, but @(':VALUES') is always a list; when a single value
 is returned, @(':VALUES') is a one-element list.  Thus, the default for
 @(':VALUES') is @('(nil)').</p>

 <p>Notice that the examples above apply @('setq') to @('st').  This
 illustrates that a variable assigned by @('setq') or @('mv-setq') must either
 be declared in a @('WITH') clause or be a known stobj.  Of course, here
 @('st') is a known stobj.  In fact, stobjs are not allowed to be declared in
 @('WITH') clauses (and that is not necessary for assigning to them).</p>

 <p>Note that it is possible to write @('DO') loops without any @('WITH')
 clauses, provided a stobj is being manipulated and measured in the body.  For
 example, using the stobj declared in the previous example,</p>

 @({
 (loop$ do
        :values (st)
        :measure (acl2-count (fld st))
        (if (endp (fld st))
            (return st)
            (if (equal 3 (car (fld st)))
                (return st)
                (setq st (update-fld (cdr (fld st)) st)))))
 })

 <p>is acceptable.  In Common Lisp, @('(loop$ do <body>)') loops until a
 @('return') is executed and so to be admissible in ACL2 some @(':measure')
 must be specified (unless there is @('return') on every branch through
 @('<body>')).  If there are no @('WITH') clauses, stobjs are the only objects
 that might be measured to explain termination, and ACL2 cannot guess effective
 measures of stobjs.</p>

 <p>To see some advice about proving inductive theorems about @('DO') loops
 measured by stobjs, see @(see stating-and-proving-lemmas-about-loop$s).</p>

 <p><b>The @('OF-TYPE') Keyword</b></p>

 <p>So far our examples have all involved @('loop$') expressions that are
 evaluated directed at the ACL2 prompt.  These do not require the @('OF-TYPE')
 keyword described in this section.  But @('loop$') expressions may also appear
 in definitions.  When these definitions are to be @(see guard)-verified,
 @('OF-TYPE') keyword may be critical.</p>

 <p>Consider the following example, which searches for an even number in a
 given list of integers, returning @('t') if one is found and else @('nil').
 As usual, we start by including the usual book for reasoning about
 @('loop$').</p>

 @({
 (include-book "projects/apply/top" :dir :system)
 (defun has-evenp (x)
   (declare (xargs :guard (integer-listp x)))
   (loop$ with temp of-type (satisfies integer-listp) = x
          do
          (cond ((endp temp)
                 (return nil))
                ((evenp (car temp))
                 (return t))
                (t
                 (setq temp (cdr temp))))))
 })

 <p>We see that the expression immediately following @('OF-TYPE') is a legal
 @(see type-spec), in this case expressing that @('(integer-listp temp)') holds
 for every value of @('temp') during execution of the @('loop$').  Let's see
 why this use of @('OF-TYPE') is necessary.  When it is omitted, guard
 verification fails with the following top-level checkpoints.</p>

 @({
 Subgoal 1.2
 (IMPLIES (AND (ALISTP ALIST)
               (NOT (CONSP (CDR (ASSOC-EQ-SAFE 'TEMP ALIST)))))
          (NOT (CDR (ASSOC-EQ-SAFE 'TEMP ALIST))))

 Subgoal 1.1
 (IMPLIES (AND (ALISTP ALIST)
               (CONSP (CDR (ASSOC-EQ-SAFE 'TEMP ALIST))))
          (INTEGERP (CADR (ASSOC-EQ-SAFE 'TEMP ALIST))))
 })

 <p>To understand these checkpoints we need to understand a bit about how ACL2
 gives a semantics to @('DO') @('loop$') expressions (as we explain in more
 detail in the section on Semantics below).  In the ACL2 logic, a @('DO')
 @('loop$') expression is represented as a transformation on an association
 list, named @('alist'), that assigns values to every variable in the
 expression.  This alist is transformed by each iteration through the loop.</p>

 <p>The value of the variable @('temp') in @('alist') is @('(assoc-eq-safe
 'temp alist)'), where @('assoc-eq-safe') is just a variant of @(tsee assoc)
 whose guard makes no requirements on the alist.  The first checkpoint
 above (Subgoal 1.2) thus says that if the value of @('temp') is not a cons,
 then it's @('nil').  That requirement comes from the expression, @('(endp
 temp)'), since the guard of @(tsee endp) is that its argument is a cons or
 @('nil').  The second checkpoint (Subgoal 1.1) says that if the value of
 @('temp') is a cons, then its @('car') is an integer.  That requirement comes
 from the expression @('(evenp (car temp))'), since the guard for @(tsee evenp)
 requires its argument to be an integer.</p>

 <p>When we add the restriction provided by the @('OF-TYPE') keyword that
 @('temp') satisfies @(tsee integer-listp), the checkpoints each get the added
 hypothesis @('(integer-listp (cdr (assoc-eq-safe 'temp alist)))').  That
 allows the guard proof to go through.  This addition also imposes that same
 requirement on the initial alist, but it is discharged because the guard for
 @('has-evenp') specifies @('(integer-listp x)') and @('temp') is initially
 assigned to @('x').  Importantly, use of the @('OF-TYPE') keyword on a
 variable imposes a guard proof obligation for every assignment to that
 variable, that the new value of that variable also satisfies the given type.
 In this case, this means that under the hypotheses that @('(endp temp)') and
 @('(evenp (car temp))') are false, and also assuming that @('temp') satisfies
 @('integer-listp') &mdash; where here, @('temp') is @('(cdr (assoc-eq-safe
 'temp alist))') &mdash; then @('(cdr temp')) satisfies @('integer-listp').
 ACL2 discharges this requirement automatically.</p>

 <p><b>The @(':GUARD') Keyword</b></p>

 <p>Consider the following definition, which is identical to the one for
 @('has-evenp') displayed above except that instead of using the @('OF-TYPE')
 keyword, it uses the @(':GUARD') keyword.</p>

 @({
 (defun has-evenp (x)
   (declare (xargs :guard (integer-listp x)))
   (loop$ with temp = x
          do
          :guard (integer-listp temp)
          (cond ((endp temp)
                 (return nil))
                ((evenp (car temp))
                 (return t))
                (t
                 (setq temp (cdr temp))))))
 })

 <p>This definition is accepted by ACL2 for much the same reason that the
 preceding one was accepted.  The difference is that while the @('OF-TYPE')
 keyword adds a requirement at every assignment of the variable, the
 @(':GUARD') imposes the invariant that when the guard holds entering the
 @('loop$') body, it also holds when the @('loop$') body is next entered.  Thus
 we see the following in the @('Goal') generated for the guard conjecture,
 where @('new-alist') is let-bound (not shown here) to the result of updating
 @('alist') after one iteration through the loop, and where @('(equal exit-flg
 nil)') indicates that another iteration is pending (because neither a
 @('return') nor a @('loop-finish') was executed).</p>

 @({
 (IMPLIES (AND (AND (ALISTP ALIST)
                    (INTEGER-LISTP (CDR (ASSOC-EQ-SAFE 'TEMP ALIST))))
               (EQUAL EXIT-FLG NIL))
          (AND (ALISTP NEW-ALIST)
               (INTEGER-LISTP (CDR (ASSOC-EQ-SAFE 'TEMP NEW-ALIST)))))
 })

 <p>The @(':guard') is generally ignored when it is within the definition's
 body for a guard-verified or a @(':')@(tsee program)-mode function.  The
 reason is that in these cases, the @('loop$') expression is converted to a
 Common Lisp @('loop') expression.  (There are exceptions involving @(tsee
 set-guard-checking) and @(see invariant-risk).)  However, in other cases the
 @(':guard') is checked at runtime.  Consider the following example.</p>

 @({
 (defun f (lst)
   (loop$ with x = lst
          do
          :guard (consp x)
          (cond ((consp x)
                 (setq x (cdr x)))
                (t (return x)))))
 })

 <p>Here we see a runtime guard violation.</p>

 @({
 ACL2 !>(f '(a b c d))


 ACL2 Error [Evaluation] in TOP-LEVEL:  The guard for a DO$ form,
 (AND (ALISTP ALIST) (CONSP (CDR (ASSOC-EQ-SAFE 'X ALIST)))),
  has been violated by the following alist:
 ((X)).
 See :DOC do-loop$.

 ACL2 !>
 })

 <p>As noted in the preceding section (on &ldquo;The @('OF-TYPE')
 Keyword&rdquo;), a call of @('do$') transforms an alist with each iteration
 through the loop.  The alist initially binds the symbol @('X') to the list
 @('(A B C D)'), and each iteration modifies that binding by @('cdr')ing the
 value of @('X'), until finally that value is @('nil') &mdash; and then a guard
 check fails for the value of @('X'), i.e., @('(CONSP (CDR (ASSOC-EQ-SAFE 'X
 ALIST)))') is @('nil').</p>

 <p>A more detailed explanation may be found in the final section,
 &ldquo;Semantics&rdquo;.</p>

 <p><b>The @(':MEASURE') Keyword</b></p>

 <p>The discussion above doesn't address the obvious possibility that a @('DO')
 @('loop$') may not terminate.  Consider the following example, which not only
 assumes that the usual book has been included as discussed above, but also
 assumes that the form @('(defwarrant princ$)') has been evaluated.</p>

 @({
 ACL2 !>(loop$ with x = '(100 200 300)
               do
               :values (state)
               (setq state (princ$ (car x) *standard-co* state)))


 ACL2 Error in TOP-LEVEL:  No :MEASURE was provided after the DO operator
 and we failed to find a likely measure.  Please supply a :MEASURE in
 (LOOP$ WITH X = '(100 200 300)
        DO :VALUES (STATE)
        (SETQ STATE
              (PRINC$ (CAR X) *STANDARD-CO* STATE))).
 See :DOC loop$.

 ACL2 !>
 })

 <p>As suggested by the error message, ACL2 has tried to guess a measure, i.e.,
 a term whose value is expected to decrease on each successive iteration.  This
 notion of ``decrease'' is the expected one when the value of the measure is a
 natural number: smaller in the sense of @('<').  In general, the measure
 decreases in the sense of @('L<') when @('lex-fix') is applied to each
 argument; see @(csee L<).</p>

 <p>Of course, no measure decreases in the example above, because the values of
 the variables don't change with each iteration.  We can see what happens when
 we supply an explicit measure: the body is evaluated, as evidenced by the
 appearance of @('100') in the output, but then the measure is evaluated and is
 seen not to have decreased from what it was at the start of the previous
 iteration.</p>

 @({
 ACL2 !>(loop$ with x = '(100 200 300)
               do
               :values (state)
               :measure (acl2-count x)
               (setq state (princ$ (car x) *standard-co* state)))
 100

 HARD ACL2 ERROR in DO$:  The measure, (ACL2-COUNT X), used in the do
 loop$ statement
 (LOOP$ WITH X = '(100 200 300)
        DO :VALUES (STATE)
        :MEASURE (ACL2-COUNT X)
        (SETQ STATE
              (PRINC$ (CAR X) *STANDARD-CO* STATE)))

 failed to decrease!  Recall that do$ tracks the values of do loop$
 variables in an alist.  The measure is computed using the values in
 the alist from before and after execution of the body.  We cannot print
 the values of double floats and live stobjs, if any are found in the
 alist, because they are raw Lisp objects, not ACL2 objects.  We print
 any double float as its corresponding rational and simply print the
 name of any live stobj (as a string).

 Before execution of the do body the alist was
 ((X 100 200 300) (STATE . "<state>")).
 After the execution of the do body the alist was
 ((X 100 200 300) (STATE . "<state>")).
 Before the execution of the body the measure was
 603.
 After the execution of the body the measure was
 603.

 Logically, in this situation the do$ returns the value of a term whose
 output signature is (STATE), where the value of any component of type
 :df is #d0.0 and the value of any stobj component is the last latched
 value of that stobj.

 ACL2 Error [Evaluation] in TOP-LEVEL: Evaluation aborted.  To debug
 see :DOC print- gv, see :DOC trace, and see :DOC wet.

 ACL2 !>
 })

 <p>Presumably the following is what was intended.</p>

 @({
 ACL2 !>(loop$ with x = '(100 200 300)
               do
               :values (state)
               :measure (acl2-count x)
               (if (atom x)
                   (return state)
                 (progn
                   (setq state (princ$ (car x) *standard-co* state))
                   (setq x (cdr x)))))
 100200300<state>
 ACL2 !>
 })

 <p>In fact, the @(':MEASURE') can be omitted in this case; ACL2 is able to
 guess @('(ACL2-COUNT X)').</p>

 <p>@(csee Guard) verification requires a proof that the measure does indeed go
 down in the sense of @('L<'), after applying @('lex-fix') to the arguments;
 see @(csee L<).  Fortunately, guard verification takes advantage of
 information specified by @('OF-TYPE') and @(':GUARD') keywords.  For example,
 the following two definitions are admitted (after the usual initial
 @('include-book') form), even though termination would not be provable without
 the @('OF-TYPE') expression in the first and the DO body's @(':GUARD') in the
 second; consider the case that @('n') is -1.</p>

 @({
 (defun foo (max)
   (declare (xargs :guard (natp max)))
   (loop$ with n of-type (satisfies natp) = max
          do
          (if (= n 0)
              (return 'stop)
            (setq n (- n 1)))))

 (defun foo (max)
   (declare (xargs :guard (natp max)))
   (loop$ with n = max
          do
          :guard (natp n)
          (if (= n 0)
              (return 'stop)
            (setq n (- n 1)))))
 })

 <p><b>A More Complex Example</b></p>

 <p>We conclude with an example presented in the documentation for @(tsee
 loop$) that illustrates all the features above.  Notice that the @(':GUARD')
 keyword may appear not only in the @('DO') body but also in the @('FINALLY')
 clause, to specify that the indicated guard holds upon entry to the
 @('FINALLY') clause.  Here we assume that we have already evaluated not only
 the usual @('include-book') form, but also the @('defstobj') and
 @('defwarrant') forms above.</p>

 @({
 (defun test-loop$ (i0 max st)
   (declare (xargs :guard (and (natp i0) (natp max))
                   :stobjs st))
   (loop$ with i of-type (satisfies natp) = i0
          with cnt of-type integer = 0
          do
          :measure (nfix (- max i))
          :guard (and (natp max)
                      (natp cnt)
                      (stp st))
          :values (nil st) ; shape of return; can be omitted when it's (nil)
          (if (>= i max)
              (loop-finish)
            (progn (setq st (update-fld i st))
                   (mv-setq (cnt i)
                            (mv (+ 1 cnt) (+ 1 i)))))
          finally
          :guard (stp st)
          (return
           (mv (list 'from i0 'to max 'is cnt 'steps 'and 'fld '= (fld st))
               st))))
 })

 <p>Notice that any variables bound above the @('loop$') may appear in it, for
 example, the formal parameters of this function.  But only variables that are
 @('WITH')-bound or declared as @(see stobj)s may be assigned with @('setq') or
 @('mv-setq').  The @(':GUARD') of @('(stp st)') is necessary, because ACL2
 does not automatically infer that stobj recognizer calls hold inside
 @('loop$') expressions the way it does in ordinary bodies of @(tsee defun)
 forms.</p>

 <p>We can evaluate the function above, as in the following example.</p>

 @({
 ACL2 !>(test-loop$ 3 8 st)
 ((FROM 3 TO 8 IS 5 STEPS AND FLD = 7)
  <st>)
 ACL2 !>
 })

 <h3>SYNTAX</h3>

 @({
 General Form:

 (LOOP$ WITH var1 OF-TYPE spec1 = init1 ; a WITH declaration
        WITH var2 OF-TYPE spec2 = init2
        ...
        DO
        :measure m
        :guard do-guard
        :values v
        do-body
        FINALLY
        :guard fin-guard
        fin-body)
 })

 <p>where much of that is optional: ``@('OF-TYPE speci')'', ``@('=
 initi')'' (when ``@('OF-TYPE speci')'' is present), ``@(':MEASURE m')'', the
 two ``@(':GUARD') ...'' clauses, ``@(':VALUES v')'', and ``@('FINALLY
 fin-body')''.  If the @(':MEASURE') is omitted, ACL2 tries to guess a likely
 measure using the same heuristic it does with recursive @(tsee defun)s.  If
 @(':VALUES') is omitted then @('v') defaults to @('(nil)'); it indicates the
 shape of the return value for the @('loop$') expression.</p>

 <p>@('Do-body') must be a cons, not an atom, as must each of the following
 that is supplied: @('m'), @('do-guard'), @('v'), @('fin-guard'), and
 @('fin-body').</p>

 <p>All ACL2 function symbols in the measure @('m') and the two bodies must be
 @(see badge)d so @(tsee apply$) can handle them.  Furthermore, they must be
 @(see warrant)ed if proofs are to be done about them or if they are in @(see
 logic) mode and are called during evaluation.</p>

 <p>The @('do-body') and @('fin-body') positions are to be what we call
 ``DO-body term''.  <b>These are not, in general, normal ACL2 terms!  They
 allow restricted uses of @('RETURN'), @('PROGN'), @('SETQ'), @('MV-SETQ'), and
 @('LOOP-FINISH') as described below.</b> In the descriptions below we ignore
 the distinctions between translated and untranslated terms; see @(see term)).
 As usual, the restrictions on return values apply only to code, not to terms
 occurring in theorem statements.</p>

 <ul>

 <li>Every ordinary term that returns a single, non-stobj value</li>

 <li>An @('IF') call whose first argument is an ordinary term (which
 necessarily returns a single, non-stobj value) and whose true and false
 branches are DO-body terms</li>

 <li>A @('LET'), @('LET*'), or @('MV-LET') expression, subject to the following
 restrictions (unless the term is an ordinary term).

 <ul>

 <li>The terms in the bindings are all ordinary terms.</li>

 <li>The body is a DO-body term.</li>

 <li>No variable bound in the bindings is @('WITH')-bound, a known @(see
 stobj), or a variable occurring free in the surrounding DO loop$
 expression.</li>

 </ul></li>

 <li>@('(PROGN term1 term2 ... termk)'), where each @('termi') is a DO-body
 term; also @('(PROG2 term1 term2)') in that case</li>

 <li>@('(RETURN term)'), where @('term') is an ordinary term</li>

 <li>@('(LOOP-FINISH)'), but only in a DO body, not in a @('FINALLY')
 clause</li>

 <li>@('(SETQ var term)'), where the variable @('var') is declared in a
 @('WITH') declaration or is a stobj name, and @('term') is an ordinary term
 that returns a single value, that value being a stobj of type @('var') if
 @('var') is a stobj</li>

 <li>@('(MV-SETQ (var0 ... varn) term)') for two or more distinct variables
 @('vari'), where each @('vari') is declared in a @('WITH') clause or is a
 stobj name, and @('term') is an ordinary term that returns n+1 values, where
 if @('vari') is a stobj then the ith value returned is of that type</li>

 </ul>

 <p>Notice that in code, where restrictions on return values are in force, no
 stobj may be let-bound in a @('DO') body or @('FINALLY') clause.  This is due
 not only to the explicit restriction above for @('LET'), @('LET*'), and
 @('MV-LET') expressions, but also due to the first condition above, on
 ordinary terms returning a single, non-stobj value.</p>

 <p>We conclude this section by discussing some syntactic restrictions.</p>

 <p>The following restriction applies to @('loop$') expressions meeting the
 following two conditions: @(':VALUES') specifies something other than the
 default of @('(NIL)'), and there is at least one @('loop-finish') expression
 in the @('loop$') body.  In that case, there must be a @('FINALLY') clause
 that ACL2 recognizes as always executing a @('return') call.  This makes
 sense, since in Common Lisp, the value returned by a @('loop') is @('nil')
 when ``falling through'' without executing a @('return'); but @('nil') would
 violate the specified @(':VALUES') in the case above.</p>

 <p>As noted above, assignments with @('setq') and @('mv-setq') may only set
 stobj variables and variables declared using @('WITH').  This restriction
 applies to the innermost @('loop$') that contains the assignment.  The
 following, for example, is illegal because the @('WITH') clause for
 @('x') is not in the @('loop$') immediately above the assignment to @('x')
 with @('setq').</p>

 @({
 (defun do-loop-nested-outer-with-var-bad (lst)
   (loop$ with x = lst
          do
          (return
           (loop$ with temp = '(1 2 3)
                  do
                  (cond ((endp temp)
                         (return (pairlis$ x x)))
                        (t (progn (setq x (cons (car temp) x))
                                  (setq temp (cdr temp)))))))))
 })

 <p>However, we expect it to be easy in general to work around this
 restriction.  The following definition, for example, accomplishes what was
 presumably intended above and is accepted by ACL2.</p>

 @({
 (defun do-loop-nested-outer-with-var (lst)
   (loop$ with x = lst
          do
          (return
           (loop$ with temp = '(1 2 3)
                  with x = x
                  do
                  (cond ((endp temp)
                         (return (pairlis$ x x)))
                        (t (progn (setq x (cons (car temp) x))
                                  (setq temp (cdr temp)))))))))
 })

 <p>Every @('return') expression in the DO body and (if present) @('FINALLY')
 clause must return a value or @(see multiple-value)s consistent with what is
 specified by the @(':VALUES') keyword (by default, a single ordinary value).
 Note that this requirement does not tolerate the replacement of a stobj by a
 stobj that is congruent to it.</p>

 <p>It is illegal for a @('loop$') expression to be in the scope of function
 bindings of an @(tsee flet) or @(tsee macrolet) expression.</p>

 <p>As noted above, the measure, body, and @('FINALLY') clauses of a DO
 @('loop$') must be fully @(see badge)d.</p>

 <p>In a function call, it is illegal for a LOOP$ expression to occur in a slot
 whose @(see ilk) is not @('nil').</p>

 <p>See the section SIGNALING ERRORS, below, for how the syntax described here
 allows for @('DO') @('loop$')s to manipulate @(tsee stobj)s and @(tsee state),
 including how to signal errors from within the body of the @('loop$').</p>

 <h3>SEMANTICS</h3>

 <p>Consider again the initial example in the Informal Introduction above.</p>

 @({
 ACL2 !>(loop$ with x = '(a b c)
               with y = nil
               do (cond ((consp x)
                         (progn (setq y (cons (car x) y))
                                (setq x (cdr x))))
                        (t (return y))))
 (C B A)
 ACL2 !>
 })

 <p>We have seen that after initializing variables using @('WITH') clauses,
 each iteration of a @('DO') @('loop$') updates those variables by evaluating
 the body of the loop (i.e., the term after the @('DO') keyword), until a
 @('return') expression is executed to return the current value of a term
 &mdash; in this case, the current value of the term, @('y').</p>

 <p>Of course, @('progn') and @('return') are not ACL2 functions!  (Recall that
 the word ``applicative'' is part of what ``ACL2'' abbreviates.)  The following
 term is essentially what is produced from the @('loop$') expression above.  We
 discuss it below.</p>

 @({
 (DO$ ; Measure Function
      (LAMBDA$ (ALIST)
               (LET ((X (CDR (ASSOC-EQ-SAFE 'X ALIST)))
                     (Y (CDR (ASSOC-EQ-SAFE 'Y ALIST))))
                    (ACL2-COUNT X)))
      ; Initial Alist
      (LIST (CONS 'X '(A B C))
            (CONS 'Y NIL))
      ; Body Function
      (LAMBDA$ (ALIST)
               (LET ((X (CDR (ASSOC-EQ-SAFE 'X ALIST)))
                     (Y (CDR (ASSOC-EQ-SAFE 'Y ALIST))))
                    (IF (CONSP X)
                        (LIST NIL
                              NIL ; irrelevant
                              (LIST (CONS 'X (CDR X))
                                    (LIST* 'Y (CAR X) Y)))
                        (LIST :RETURN
                              Y
                              (LIST (CONS 'X X) (CONS 'Y Y))))))
      ... ; Other arguments are omitted here.
 )
 })

 <p>The display above is approximate; in particular, it hides some logically
 irrelevant clutter such as @(tsee declare) forms and it shows only arguments
 of @('do$') relevant to our discussion of the example above.  Also, the
 display employs user-level syntax (i.e., an <i>untranslated term</i>; see
 @(see term)).  See also the subsection of @(tsee lambda$) entitled ``About
 @('Lambda$')s and Prover Output.''</p>

 <p>The definition of @('do$') is given later in this topic, for those who care
 to explore it, but this discussion is intended to be self-contained.  @('Do$')
 operates by maintaining an alist that maps variables to values, for all
 variables referenced in the @('loop$') expression &mdash; though only
 variables that are declared in @('WITH') clauses or are stobjs may be
 modified.  This alist is updated on each iteration by calling @(tsee apply$)
 on the ``Body Function'' above, producing a 3-element list @('(exit-token val
 new-alist)').  If @('exit-token') is @(':RETURN') then @('val') is returned.
 But if @('exit-token') is @('nil'), then @('do$') is called recursively with
 @('new-alist') as its alist argument.</p>

 <p>To see @('do$') in action one can submit the following forms.  Here the
 body of @('f') is just the @('loop$') expression shown above.  Notice that
 @('f') is not @(see guard)-verified; after submitting @('(verify-guards f)')
 the @('loop$') expression is evaluated as a Common Lisp @('loop') call rather
 than using @('do$'), so there would be no @(see trace) output.  Don't worry
 about having a precise understanding of the fancy calls of @(tsee trace!); the
 comments there should suffice.</p>

 @({
 (include-book "projects/apply/top" :dir :system)
 (defun f ()
   (loop$ with x = '(a b c)
          with y = nil
          do (cond ((consp x)
                    (progn (setq y (cons (car x) y))
                           (setq x (cdr x))))
                   (t (return y)))))
 ; Store the translated body function so that we can access it later
 ; with (@ my-body-fn):
 (trace! (do$ :entry (f-put-global 'my-body-fn (nth 2 arglist) state)))
 ; Run f to store to my-body-fn as commented above.
 (f)
 ; Trace do$ calls and trace calls of apply$ on the body function.
 (trace! (do$ :notinline t ; include recursive calls
              :cond (eq traced-fn 'do$) ; skip *1* call
              :entry (list traced-fn alist))
         (apply$ :cond (equal (car arglist) (@ my-body-fn))
                 :entry (list traced-fn
                              (cadr arglist) ; the alist
                        )))
 (f)
 })

 <p>Here is the trace output from the final call of @('f') above; analysis
 follows.</p>

 @({
 ACL2 !>(f)
 1> (DO$ ((X A B C) (Y)))
   2> (APPLY$ (((X A B C) (Y))))
   <2 (APPLY$ (NIL NIL ((X B C) (Y A))))
   2> (DO$ ((X B C) (Y A)))
     3> (APPLY$ (((X B C) (Y A))))
     <3 (APPLY$ (NIL NIL ((X C) (Y B A))))
     3> (DO$ ((X C) (Y B A)))
       4> (APPLY$ (((X C) (Y B A))))
       <4 (APPLY$ (NIL NIL ((X) (Y C B A))))
       4> (DO$ ((X) (Y C B A)))
         5> (APPLY$ (((X) (Y C B A))))
         <5 (APPLY$ (:RETURN (C B A) ((X) (Y C B A))))
       <4 (DO$ (C B A))
     <3 (DO$ (C B A))
   <2 (DO$ (C B A))
 <1 (DO$ (C B A))
 (C B A)
 ACL2 !>
 })

 <p>First consider the calls of @('do$') above.  You can see that @('X') is
 initially bound in the alist to @('(A B C)'), but on successive @('do$')
 calls, @('X') is bound to successive @('cdr')s of @('(A B C)').  Meanwhile,
 the accumulator variable @('Y') is initially bound to @('NIL') but at each
 call of @('do$'), the next @('car') of @('(A B C)') is pushed onto the binding
 of @('Y').  Now consider the calls of @(tsee apply$).  Up until the last call,
 @('apply$')ing the body function results in a triple of the form @('(mv nil
 nil new-alist)'), where @('new-alist') is supplied as the alist argument for
 the next @('do$') call.  The last call of @('apply$') on the body function
 gives the result @('(mv :RETURN (C B A) new-alist)'), where @('(C B A)') is
 the value returned by the calls of @('do$').</p>

 <p>Now consider this variant of the above example, which was given above when
 introducing @('FINALLY') clauses.</p>

 @({
 ACL2 !>(loop$ with x = '(a b c)
               with y = nil
               do (cond ((consp x)
                         (progn (setq y (cons (car x) y))
                                (setq x (cdr x))))
                        (t (loop-finish)))
               finally (return y))
 (C B A)
 ACL2 !>
 })

 <p>The corresponding @('do$') call is similar to that of the preceding
 example, but notice @(':LOOP-FINISH') in place of @(':RETURN'), and notice
 that we show the fourth argument this time: the function corresponding to the
 @('FINALLY') clause.</p>

 @({
 (DO$ ; Measure Function
      (LAMBDA$ (ALIST)
               (LET ((X (CDR (ASSOC-EQ-SAFE 'X ALIST)))
                     (Y (CDR (ASSOC-EQ-SAFE 'Y ALIST))))
                    (ACL2-COUNT X)))
      ; Initial Alist
      (LIST (CONS 'X '(A B C))
            (CONS 'Y NIL))
      ; Body Function
      (LAMBDA$ (ALIST)
               (LET ((X (CDR (ASSOC-EQ-SAFE 'X ALIST)))
                     (Y (CDR (ASSOC-EQ-SAFE 'Y ALIST))))
                    (IF (CONSP X)
                        (LIST NIL
                              NIL ; irrelevant
                              (LIST (CONS 'X (CDR X))
                                    (LIST* 'Y (CAR X) Y)))
                        (LIST :LOOP-FINISH
                              NIL ; irrelevant
                              (LIST (CONS 'X X) (CONS 'Y Y))))))
      ; FINALLY function
      (LAMBDA$ (ALIST)
               (LET ((X (CDR (ASSOC-EQ-SAFE 'X ALIST)))
                     (Y (CDR (ASSOC-EQ-SAFE 'Y ALIST))))
                    (LIST :RETURN
                          Y
                          (LIST (CONS 'X X) (CONS 'Y Y)))))
      ; Values (output signature)
      '(NIL)
      ... ; Last argument omitted here.
 )
 })

 <p>Above, we also took the opportunity to show the fifth argument of @('do$'),
 which is the output signature of the logical value to be returned should the
 measure fail to decrease.  That output signature is specified with the
 @(':VALUES') keyword in a @('do') @('loop$').  If omitted and the @('loop$')
 returns a single ordinary object, the output signature is @('(nil)') as here.
 The @('values') argument to @('do$') is passed along unchanged as the function
 iterates and, should the measure fail to decrease, the signature is used to
 compute a default answer.  However, that default answer is never relevant to
 evaluations because a hard ACL2 error actually occurs.  The default answer may
 be relevant when reasoning about @('do$') calls.  Since guard verification of
 a @('do') @('loop$') guarantees termination, the default answer is never
 relevant when dealing with guard verified functions containing @('do')
 @('loop$')s.</p>

 <p>Here is the definition of @(tsee do$).</p>

 @(def do$)

 <p>We conclude by returning to an earlier example that illustrates runtime
 guard-checking.  But this time we do some tracing, as indicated.</p>

 @({
 (defun f (lst)
   (loop$ with x = lst
          do
          :guard (consp x)
          (cond ((consp x)
                 (setq x (cdr x)))
                (t (return x)))))
 (trace! (do$ :entry (list traced-fn alist) :notinline t))
 (trace$ do-body-guard-wrapper)
 })

 <p>As before, we have a guard violation.  The trace output is explained
 below.</p>

 @({
 ACL2 !>(f '(a b c d))
 1> (ACL2_*1*_ACL2::DO$ ((X A B C D)))
   2> (DO$ ((X A B C D)))
     3> (DO-BODY-GUARD-WRAPPER T NIL)
     <3 (DO-BODY-GUARD-WRAPPER T)
     3> (DO-BODY-GUARD-WRAPPER T NIL)
     <3 (DO-BODY-GUARD-WRAPPER T)
     3> (DO-BODY-GUARD-WRAPPER T NIL)
     <3 (DO-BODY-GUARD-WRAPPER T)
     3> (DO$ ((X B C D)))
       4> (DO-BODY-GUARD-WRAPPER T NIL)
       <4 (DO-BODY-GUARD-WRAPPER T)
       4> (DO-BODY-GUARD-WRAPPER T NIL)
       <4 (DO-BODY-GUARD-WRAPPER T)
       4> (DO-BODY-GUARD-WRAPPER T NIL)
       <4 (DO-BODY-GUARD-WRAPPER T)
       4> (DO$ ((X C D)))
         5> (DO-BODY-GUARD-WRAPPER T NIL)
         <5 (DO-BODY-GUARD-WRAPPER T)
         5> (DO-BODY-GUARD-WRAPPER T NIL)
         <5 (DO-BODY-GUARD-WRAPPER T)
         5> (DO-BODY-GUARD-WRAPPER T NIL)
         <5 (DO-BODY-GUARD-WRAPPER T)
         5> (DO$ ((X D)))
           6> (DO-BODY-GUARD-WRAPPER T NIL)
           <6 (DO-BODY-GUARD-WRAPPER T)
           6> (DO-BODY-GUARD-WRAPPER NIL NIL)
           <6 (DO-BODY-GUARD-WRAPPER NIL)


 ACL2 Error [Evaluation] in TOP-LEVEL:  The guard for a DO$ form,
 (AND (ALISTP ALIST) (CONSP (CDR (ASSOC-EQ-SAFE 'X ALIST)))),
  has been violated by the following alist:
 ((X)).
 See :DOC do-loop$.

 ACL2 !>
 })

 <p>To understand the trace output above, we first take a look at the
 translation of the @('loop$') expression above.  This time we show the
 corresponding @('do$') form with @(tsee declare) forms included, but as
 before some parts of this form are simplified, untranslated, or elided.  (You
 can see the exact translation by applying @(':')@(tsee trans) to the @('do$')
 call.)  Note that @('do-body-guard-wrapper') is just an identity function (on
 its first argument) used by the implementation, but it is handy here for the
 explanation that follows.</p>

 @({
 (DO$
   ;; measure:
   '(LAMBDA (ALIST)
     (DECLARE
      (XARGS :GUARD
             (DO-BODY-GUARD-WRAPPER
              (AND (ALISTP ALIST)
                   (CONSP (CDR (ASSOC-EQ-SAFE 'X ALIST))))
              NIL)))
     ((LAMBDA (X) (ACL2-COUNT X))
      (CDR (ASSOC-EQ-SAFE 'X ALIST))))
   ;; alist:
   (LIST (CONS 'X LST))
   ;; body:
   '(LAMBDA (ALIST)
     (DECLARE
      (XARGS :GUARD
             (DO-BODY-GUARD-WRAPPER
              (AND (ALISTP ALIST)
                   (CONSP (CDR (ASSOC-EQ-SAFE 'X ALIST))))
              NIL)))
     ((LAMBDA (X)
              (IF (CONSP X)
                  (LIST NIL NIL
                        (LET ((X (CDR X))) (LIST (CONS 'X X))))
                  (LIST :RETURN X (LIST (CONS 'X X)))))
      (CDR (ASSOC-EQ-SAFE 'X ALIST))))
   .....)
 })

 <p>Recall that @('do$') works by repeatedly applying the given lambda to its
 alist argument, which initially binds @(''X') to @('LST') as shown above.
 @('Do$') recurs when that application returns a triple @('(mv nil nil
 new-alist)'), where @('new-alist') is the alist returned by the body of the
 @('loop$') expression.  But when @('do$') applies the given @(see lambda)
 object, it first checks the @(':guard') of that lambda.  We also see that
 before @('do$') recurs, it applies its @('measure-fn') argument to the input
 alist and to @('new-alist').</p>

 <p>So let's focus on the following from the end of the trace output above.</p>

 @({
         5> (DO$ ((X D)))
           6> (DO-BODY-GUARD-WRAPPER T NIL)
           <6 (DO-BODY-GUARD-WRAPPER T)
           6> (DO-BODY-GUARD-WRAPPER NIL NIL)
           <6 (DO-BODY-GUARD-WRAPPER NIL)
 })

 <p>The first @('DO-BODY-GUARD-WRAPPER') call comes from the guard of the
 lambda that represents the body of the @('do$') loop, from the expression
 @('(apply$ do-fn (list alist))') in the definition of @('do$') (above).  Here
 @('alist') is @('((X D))'), so the conjunct @('(CONSP (CDR (ASSOC-EQ-SAFE 'X
 ALIST)))') from that lambda's guard is true.  The second call of
 @('DO-BODY-GUARD-WRAPPER') comes from the expression @('(apply$
 measure-fn (list new-alist))') in the definition of @('do$').  But
 @('new-alist') is @('nil'), so the conjunct @('(CONSP (CDR (ASSOC-EQ-SAFE 'X
 ALIST)))') from the measure lambda's guard is false, so the guard evaluates to
 @('nil').</p>

 <h3>SIGNALING ERRORS</h3>

 <p>We explain the subtleties of error signaling from within @('DO')
 @('loop$')s by example.  To illustrate the full complexity of the situation,
 our example will involve a @('DO') that is manipulating a @(see stobj), and
 we'll verify the guards.  The basic idea is that we'll define a function,
 called @('transaction'), that either detects and signals an error or updates
 the stobj, and then we'll write a @('DO') @('loop$') that executes a series of
 transactions.  In fact, you may think of the stobj as representing an account
 that must maintain a non-negative balance and the transaction as taking an
 integer and adding it to the balance provided that doesn't produce a negative
 balance.  Managing the signatures of the various functions in body of the
 @('loop$') and declaring the ``right'' guards takes some experience.  After
 we've presented a correct solution we will show some plausible alternatives
 and explain why they are unacceptable.</p>

 <p>Recall that the standard idiom for signaling a ``soft'' error in ACL2 is to
 call the function @(tsee error1), usually via the macro @(tsee er).
 @('Error1') returns an @(see error-triple) of the form @('(mv t nil state)').
 So our @('DO') @('loop$') will necessarily manipulate @('state') in addition
 to the user's stobj.</p>

 <p>To admit the functions shown below, first execute these three commands.</p>

 @({
 (include-book "projects/apply/top" :dir :system)
 (set-state-ok t)
 (defstobj st (balance :type (satisfies natp) :initially 0))
 })

 <p>Note that our stobj has just one field, named @('balance'), which must be a
 natural number and is initially 0.  Below is the basic @('transaction')
 function which may signal an error.  Note that two unnecessary lines are
 commented out as explained in note [1] below.</p>

 @({
  (defun transaction (delta st state)
    (declare (xargs :stobjs (st state)
                    :guard (and (integerp delta)
  ;                             (stp st)                     ; [1]
  ;                             (state-p state)              ; [1]
                                (error1-state-p state))))    ; [2]
    (cond ((< (balance st) (- delta))
           (mv-let (erp val state)                           ; [3]
             (er soft 'transaction
                 "The stobj's balance is ~x0 but the delta is ~x1, so this ~
                  transaction is not allowed!"
                 (balance st)
                 delta)
             (declare (ignore val))
             (mv erp st state)))
          (t (let ((st (update-balance (+ (balance st) delta)
                                       st)))
               (mv nil st state)))))
  })

  <p>Notes on @('transaction'):</p>

  <ul>

  <li>[1] We don't need to include @('(stp state)') and @('(state-p state)')
    explicitly in the @(':guard') for the function because they're implicitly
    included by the @(':stobjs') declaration.</li>

  <li>[2] The @(tsee er) macro expands to a call of the function @(tsee
    error1), and @('error1') requires that its @(tsee state) argument not only
    satisfy the recognizer for ACL2 states, @('state-p'), but also some
    other conditions to allow formatted printing to certain channels.  See
    @(':')@(tsee pe) @('error1-state-p') and its subroutine @('fmt-state-p').
    By the way, you won't see ``@('(state-p state)')'' in the @(':guard')
    declaration of @('error1').  But it is implicit in the use of the variable
    named @('state') as a formal.  To see the full guard of a function,
    <i>fn</i>, you can do @(':')@(tsee args) <i>fn</i> or,
    alternatively, @('(guard '')<i>fn</i>@(' nil (w state))').</li>

  <li>[3] We signal an error with the @('er') macro.  But the signature of
    @('er') is @('(mv * * state)'), i.e., the first two values returned are
    ``ordinary'' objects, not stobjs.  But our function, @('transaction'), must
    return the (possibly) modified stobj @('st').  So we ``catch'' the error
    triple generated by @('er') and replace the ordinary @('val'), which in
    this case is @('nil'), by @('st').</li>
  </ul>

 <p>Since we'll use @('transaction') in a @('DO') @('loop$'), we need a
 warrant.</p>

 @({
 (defwarrant transaction)
 })

 <p>The lemma below is not strictly necessary.  If we don't prove it here, the
 guard proof for our @('loop$') takes longer because we have to prove a more
 complicated instance of this lemma by induction.</p>

 @({
 (defthm dumb-lemma
   (implies (and lst
                 (integer-listp lst))
            (integerp (car lst)))
   :rule-classes :type-prescription)
 })

 <p>Finally, we define the function that executes a series of @('transaction')s
 on a sequence of integers.  But it may detect and signal an error partway
 through the sequence.  Note that several lines are commented out, either
 because they are optional or because they are prohibited, as explained in the
 accompanying notes below.</p>


 @({
 (defun transaction-loop (delta-lst st state)
   (declare (xargs :stobjs (st state)
                   :guard (and (integer-listp delta-lst)
 ;                             (stp st)                     ; See Note [1] above
 ;                             (state-p state)              ; See Note [1] above
                               (error1-state-p state))
                   :guard-hints (("Goal" :in-theory (enable error1)))))
   (loop$ with lst = delta-lst
 ;        with st                                           ; [4]
 ;        with state                                        ; [4]
          with erp                                          ; [5]
          do
          :guard (and (integer-listp lst)
                      (stp st)                              ; [6]
                      (state-p state)                       ; [6]
                      (error1-state-p state))
          :values (nil st state)
          (cond
           ((eq lst nil) (return (mv nil st state)))
           (t (progn                                        ; [7]
                (mv-setq (erp st state)
                         (transaction (car lst) st state))
                (cond
                 (erp (return (mv erp st state)))
                 (t (setq lst (cdr lst)))))))))
 })

 <p>Notes on @('transaction-loop'):</p>

 <ul>

 <li>[4] One might think that we need to bind @('st') and @('state') in
     @('WITH') clauses because, in the body of the @('DO') @('loop$'), we
     assign to them, with @('mv-setq'), here, or in other examples, with
     @('setq').  But ACL2 disallows binding stobj names in @('WITH') clauses.
     A syntax error is signaled if you try that.</li>

 <li>[5] We must bind @('erp') in a @('WITH') clause because we assign to it
     in the body and it is an ordinary object.</li>

 <li>[6] One might think that we do not need to include @('(stp st)') and
     @('(state-p state)') in the @(':guard') of the @('DO') @('loop$') body,
     for the same reasons we did not have to include them in the @(':guard') of
     the function itself: might they be implicitly included by virtue of their
     being stobj names?  The answer is no!  If a stobj is used in the body of a
     @('DO') @('loop$'), the @(':guard') for the @('DO') @('loop$') must
     include the stobj recognizer if guard checking is to succeed.</li>

 <li>[7] Finally, the construction

     @({
     (progn (mv-setq (erp st state) <term>) <do-body-term>)
     })

     used here may seem odd.  One might be inclined to write something like
     this instead:

     @({
     (mv-let (erp st state) <term> <do-body-term>)
     })

     However, the latter construction is syntactically illegal in the body
     of a @('DO') @('loop$').  The reason has to do with the precise definition
     of ``do-body terms'' (see the SYNTAX section above).  Recall that do-body
     terms are term-like but allow very restricted uses of @('return'),
     @('progn'), @('setq'), @('mv-setq'), and @('loop-finish') and possibly
     other do-body subterms.  Do-body terms are not actually ACL2 terms!

     <p/>To be precise, one might have tried to use the following as the body
     of the @('loop$') in @('transaction-loop').

     @({
     (cond
       ((eq lst nil) (return (mv nil st state)))
       (t (mv-let (erp st state)
                  (transaction (car lst) st state)
            (cond
             (erp (return (mv erp st state)))
             (t (setq lst (cdr lst)))))))
     })

     Note the @('mv-let').  It is syntactically illegal because its final
     argument, namely the @('cond')-expression, uses @('return') and @('setq')
     where ACL2 function names are required.  In writing the above, the user
     has presumed that an @('mv-let') expression in a do-body term allows the
     final argument to be a do-body term instead of an ACL2 term.  This
     presumption is incorrect.  Instead, use @('progn') and @('mv-setq') to
     field the values of a multi-valued function like @('transaction') and then
     write the do-body term to process them.</li>

 </ul>

 <p>Here is a sample session log after introducing the correct definitions
 above.  Note that the balance starts at 0, the user, employing the function
 @('transaction'), adds 100 and then attempts to subtract 150.  An error is
 signaled and the balance remains 100.  Then the user runs the
 @('transaction-loop') function with a starting balance of 100 and attempts to
 successively subtract 20, then 30, then 55, and then attempts to add 200.  The
 loop terminates with an error on the 55 and leaves the balance at 50, never
 processing the 200.</p>

 @({
 ACL2 !>(balance st)
 0
 ACL2 !>(transaction 100 st state)
 (NIL <st> <state>)
 ACL2 !>(balance st)
 100
 ACL2 !>(transaction -150 st state)


 ACL2 Error in TRANSACTION:  The stobj's balance is 100 but the delta
 is -150, so this transaction is not allowed!

 (T <st> <state>)
 ACL2 !>(balance st)
 100
 ACL2 !>(transaction-loop '(-20 -30 -55 200) st state)


 ACL2 Error in TRANSACTION:  The stobj's balance is 50 but the delta
 is -55, so this transaction is not allowed!

 (T <st> <state>)
 ACL2 !>(balance st)
 50
 })

 ")
other
(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>")
other
(defxdoc doc
  :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 (when the @(see xdoc) system has
 been included) it can also access other documentation topics defined in the
 current session, including via included 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>If you are not happy with the way text is displayed using @(':doc'), see
 @(see xdoc::terminal).</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>

 <p>Note that @(see community-book) @('xdoc/top') redefines @(':doc') (using
 @(see add-ld-keyword-alias!)) to invoke the similar macro @('xdoc'), which can
 access documentation topics defined in books.</p>")
other
(defxdoc doc-terminal-test-1
  :parents (documentation)
  :short "Short"
  :long "<p><b>Symbol @('EQUAL') and the rest is still bold.</b></p>")
other
(defxdoc doc-terminal-test-2
  :parents (documentation)
  :short "Short"
  :long "<p><u>Start underline <b>Start bold <i>Start italics <tt>TYPEWRITER
 FONT [WHICH ENDS HERE]</tt> Bold italics underlined</i> Bold underlined.</b>
 Underlined</u> Normal text</p>")
other
(defxdoc documentation
  :parents (top)
  :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>When you type @(':DOC <topic>') at the terminal for a given @('<topic>'),
 ACL2 responds with documentation for that topic.  Unless you include books
 that incorporate additional documentation, @('<topic>') must be documentation
 that is provided with the ACL2 system (not the @(see community-books)).</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>

 <p><b>Remark for Experienced Users</b>.  Occasionally it might make sense to
 add a link to your book's documentation from the ACL2 system documentation,
 which is in @(see community-book) @('books/system/doc/acl2-doc.lisp'). You are
 welcome to do so, but in that case, also add to the constant
 @('*acl2-broken-links-alist*') near the top of that file, as described in a
 comment in that constant.  For example, that constant's value has the
 following line.</p>

 @({
     (FTY::DEFPROD "[books]/centaur/fty/top.lisp")
 })

 <p>That line may have been added because in the form @('(defxdoc defrec ...)')
 in @('acl2-doc.lisp'), we find a link to @('fty::defprod').  You can do
 similarly for your own added link.</p>

 <p>If your topic is not in the @('"ACL2"') package, such as in the example
 link @('fty::defprod') above, then add a suitable @(tsee include-book) form to
 @('books/system/doc/cert.acl2').  For example, that file includes the line</p>

 @({
 (include-book "centaur/fty/portcullis" :dir :system)
 })

 <p>in order to define the @('"FTY"') package.  End of Remark for
 Experienced Users</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>")
other
(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 the basis for using the @(':')@(tsee DOC) command
 at the terminal when ACL2 starts up.  Its source in the ACL2 @(see
 community-books) as file @('books/system/doc/acl2-doc.lisp').  Members of the
 ACL2 community contribute to it, although its original authors are the ACL2
 authors.  It is copyrighted under the terms of the @('LICENSE') file
 distributed with ACL2.</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>")
other
(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&amp;rep=rep1&amp;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)))
 })")
other
(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 (:e fn)))         ; equivalent to (enable lemma1 (:e fn))
  (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).  Note that the concluding @('disables-n') may be omitted.</p>

 <p>The @('e/d') macro takes any number of lists suitable for the @(tsee
 enable) and @(tsee disable) macros.  The event</p>

 @({
 (in-theory (e/d (e00 e01 e02 ...) (d00 d01 d02 ...)
                 ...
                 (en0 en1 en2 ...) (dn0 dn1 dn2 ...)
 })

 <p>creates a theory that is equivalent to the following sequence of @(tsee
 in-theory) events.  (An analogous similar effect takes place for
 @(':in-theory') @(see hints).</p>

 @({
 (in-theory (enable e00 e01 e02 ...))
 (in-theory (disable d00 d01 d02 ...))
 ...
 (in-theory (enable en0 en1 en2 ...))
 (in-theory (disable dn0 dn1 dn2 ...))
 })")
other
(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>")
other
(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 Forms:
  (ec-call (fn term1 ... termk))
  (ec-call (fn term1 ... termk) :dfs-in 'dfs-in :dfs-out dfs-out)
 })

 <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 Note on
 Inlining below for an exception pertaining to inlining.)  In particular,
 @('fn') is not a macro.  The second form is only relevant for those who use
 @(see df)s and is discussed at the end of this topic.</p>

 <p>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>Note on Inlining.  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>

 <p>We conclude with a discussion of the second General Form:</p>

 @({
  (ec-call (fn term1 ... termk) :dfs-in 'dfs-in :dfs-out 'dfs-out)
 })

 <p>Note that either or both keyword arguments may be omitted, and if both are
 included then they can be given in either order.</p>

 <p>See @(see df) for background on dfs.  Here is an example.</p>

 @({
 ACL2 !>(ec-call (binary-df+ (df1) (df1)) :dfs-in '(t t) :dfs-out '(t))
 #d2.0
 ACL2 !>
 })

 <p>The keyword arguments indicate, respectively, @('binary-df+') takes two df
 arguments and returns a single df value.  Without those arguments ACL2 would
 report an error.</p>

 <p>The next example illustrates the use of @(':dfs-out') for multiple value
 returns.  First define @('g') as follows.</p>

 @({
 (defun g (x)
   (mv (df+ (df1) (to-df x)) (- x 1)))
 })

 <p>The use of @(':dfs-out') below tells ACL2 that the given expression @('(g
 3)') returns two values: a df and an ordinary value.  In the language of :DOC
 @(see df): @('(g 3)') is a df{0} expression and is not a df{1} expression.
 Note that the argument of @('g') is an ordinary expression, not a df, so no
 @(':dfs-in') argument is necessary.</p>

 @({
 ACL2 !>(ec-call (g 3) :dfs-out '(t nil))
 (#d4.0 2)
 ACL2 !>
 })

 <p>Returning to the second General Form, notice that @('dfs-in') and
 @('dfs-out') are lists of Booleans, which must be quoted, that indicate for
 @('fn') which inputs or values (respectively) are dfs.  For example, if
 @('fn') returns a single value, then @('dfs-out') is @('(t)') if the call of
 @('fn') is a df, else @('dfs-out') is optional but may be supplied as
 @('(nil)').  If @('fn') returns n values where n is greater than 1, then
 @('dfs-out') should be a list of length n where for each zero-based index i
 less than n, the ith element of @('dfs') is @('t') if the ith return value is
 a df (or more precisely, in the language of :DOC @(see df), calls of @('fn')
 are df{i} expressions), else @('nil').  The rules for the @(':dfs-in')
 argument are analogous for inputs of the call of @('fn').</p>

 <p>When there are no df inputs (respectively, outputs) of the call, then
 @(':dfs-in') (respectively, @(':dfs-out') may be omitted or supplied as
 @('nil') or @(''nil').</p>")
other
(defxdoc efficiency
  :parents (debugging proof-automation programming)
  :short "Efficiency considerations"
  :long "<p>This topic is a grab-bag of ideas for the efficient use of ACL2,
 including proofs and programming.  It is far from complete, and @(see tips)
 for using ACL2 effectively may be found throughout the @(see documentation).
 The present topic will, ideally, improve over time, both in its content and in
 its organization.  Please contribute!</p>

 <p>Here we discuss primarily time efficiency rather than space efficiency.
 You can time forms using @(tsee time$).  That may show you that your tweaks
 to proof scripts or function definitions don't make a noticeable difference!
 We focus below on some techniques that have a reasonable chance of making a
 difference.</p>

 <h3>Proof efficiency</h3>

 <p>Perhaps the most basic idea for carrying out proofs efficiently is to use
 rewriting effectively; see @(see introduction-to-the-theorem-prover) and, in
 particular, the sections on rewriting.  Here we mention just a few common ways
 to improve the efficiency of rewriting in ACL2.</p>

 <ul>

 <li>Consider minimizing the number of hypotheses of a rule.  See @(see
 remove-hyps) for a tool that can help with that.</li>

 <li> Manage @(see theories) effectively.  See @(see accumulated-persistence)
 for a way to identify rules that might best be @(see disable)d.  In
 particular, it can be useful to disable functions whose expansions generate
 large case splits (see @(see splitter)); otherwise, sometimes it can be useful
 to limit case-splits with @(tsee set-case-split-limitations).</li>

 <li>When many similar proofs are being performed (for example, for families of
 similar theorems generated by macros), the tool @(see removable-runes) may be
 helpful.</li>

 </ul>

 <p>Sometimes rewriting is slow for inherent algorithmic reasons.  For example,
 if you have a binary function, @('op'), and you prove the @(see rewrite) rules
 @('(equal (op x y) (op y x)')) and @('(equal (op x (op y z)) (op y (op x
 z)))'), then ACL2 will use an @('n^2') algorithm to put arguments in order,
 essentially with bubblesort, in a sequence like this:</p>

 @({
 (op d (op c (op b a)))
 (op d (op c (op a b)))
 (op d (op a (op c b)))
 (op d (op a (op b c)))
 (op a (op d (op b c)))
 (op a (op b (op d c)))
 (op a (op b (op c d)))
 })

 <p>In such a case, you may find it very helpful to create a suitable @(see
 meta) rule or a @(see clause-processor) rule, to implement an @('n*log(n)')
 algorithm.  You may consider creating calls of @(tsee hide) to avoid exploring
 terms that are in the expected form.  Calls of @('hide') may be removed when
 ready either with a suitable @(':expand') hint or by enabling a @(see rewrite)
 rule @('(equal (hide x) x)').</p>

 <p>We conclude this section with ways to tweak the ACL2 system to speed up
 slow proofs.  These can be especially useful if very large terms are involved.
 One simple thing to try is to turn off the rewrite cache.</p>

 @({
 (set-rw-cache-state nil)
 })

 <p>Some system behaviors can be modified using @(tsee defattach-system)
 &mdash; also see @(see system-attachments) &mdash; typically by modifying
 heuristics.  You can find all attachments by evaluating @('(all-attachments (w
 state))') and all built-in such attachments by evaluating @('(global-val
 'attachments-at-ground-zero (w state))'), except for a few exceptions (see
 @(see defattach)).  For most of these, however, you will need to consult the
 ACL2 source files for relevant information.  Here are some key examples of how
 to modify system behavior.</p>

 @({
 (defun constant-nil-function-arity-2 (x y)
   (declare (xargs :mode :logic :guard t) (ignore x y))
   nil)
 (defattach-system too-many-ifs-post-rewrite
   constant-nil-function-arity-2)
 (defattach-system too-many-ifs-pre-rewrite
   constant-nil-function-arity-2)
 (defattach-system quick-and-dirty-srs
   constant-nil-function-arity-2)
 })

 <p>In some cases books may provide more sophisticated uses of @(tsee
 defattach-system) (or @(tsee defattach)).  For a key example, see @(tsee
 use-trivial-ancestors-check).</p>

 <p>Another way to speed up system functions can be by using @(see
 memoization).  Here is an example from
 @('books/projects/stateman/stateman22.lisp').</p>

 @({
 (memoize 'acl2::sublis-var1
          :condition '(and (null acl2::alist)
                           (consp acl2::form)
                           (eq (car acl2::form) 'HIDE)))
 })

 <p>See @(see memoized-prover-fns) for a convenient way to do such memoization
 that automatically clears memoization tables after each event.  (Also see
 @(see clear-memoize-table) and @(see clear-memoize-tables), and see @(see
 hons-wash) for another way to clean up after memoization.)  Comments in the
 book @('books/tools/memoize-prover-fns.lisp') note a reduction in proof time
 from 4200 seconds to 49 seconds for one example by memoizing some system
 functions.  Those comments also have some discussion about which system
 functions to consider memoizing.  Perhaps ACL2 users will contribute further
 documentation on which system functions to memoize for efficiency.</p>

 <p>The following may be helpful at the level of book certification, and are
 discussed in :doc certify-book-debug.</p>

 @({
 (set-serialize-character-system nil)
 (set-bad-lisp-consp-memoize nil)
 (set-inhibit-output-lst '(proof-tree event))
 })

 <h3>Programming efficiency</h3>

 <p>Ideas for efficient programming include the use of compilation for host
 Lisps (other than CCL and SBCL, which compile automatically); see @(see comp)
 and @(see set-compile-fns).  For @(see logic)-mode functions, verify @(see
 guard)s if feasible; otherwise consider using @(see program)-mode wrappers
 (see @(see program-wrapper)).  Consider writing recursive definitions using
 tail recursion when possible.  In some cases the use of hash cons,
 memoization, or fast alists may reduce computation time dramatically; see
 @(see hons-and-memoization).  Single-threaded objects (see @(see stobj)),
 @(see arrays), @(see multiple-value) return, and @(tsee mbe) are helpful
 programming constructs provided by ACL2 for efficient execution.  Some
 built-in functions are constructed for efficiency; see for example @(tsee
 cons-with-hint) to reduce consing and @(see read-file-into-string) for
 obtaining the contents of a file quickly.</p>

 <p>You might find @(tsee type) @(see declaration)s to be useful.  In
 particular, if your host Lisp is GCL then the use of the declaration
 @('(signed-byte 64)'), or any stronger declaration (e.g., @('(unsigned-byte
 63)'), @('(signed-byte 12)'), or @('(integer 0 100)')), can provide dramatic
 performance improvements in compiled code.  You can peruse that code using
 @(see disassemble$).</p>

 <p>Of course, if a programming technique or construct is useful for efficient
 execution in Common Lisp and it is supported by ACL2, then it is useful for
 efficient execution in ACL2.  In particular, consider using @(tsee type) @(see
 declaration)s for numbers in place of @(tsee xargs) @(':')@(tsee guard).</p>

 <h3>Miscellaneous efficiency ideas</h3>

 <p>The use of @(tsee make-event) can sometimes reduce computation time; see
 for example @(see using-tables-efficiently) and @(see defconsts).</p>

 <p>You can @(see profile) functions to see where time is being spent during
 proofs or when computing with user-defined functions.  Sometimes it is even
 useful to profile virtually all ACL2 source functions, or even virtually all
 user-defined functions.  That can be done as follows &mdash; also see @(see
 profile-acl2) and @(see profile-all) &mdash; but note that when the problem is
 slow proofs, then since the results will display time spent in various ACL2
 prover routines, those results might not be helpful to most users.</p>

 @({
 (include-book "centaur/memoize/old/profile" :dir :system)
 (profile-acl2) ; or, (profile-all) to include user-defined functions
 [[Then run a slow form.]]
 (memsum) ; shows where time is spent
 })

 <p>For computations and proofs that may benefit from parallel computation, you
 could build the variant ACL2(p) of ACL2.  See @(see parallelism).</p>

 ")
other
(defxdoc eighth
  :parents (nth acl2-built-ins)
  :short "Eighth member of the list"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(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>An @(':elim') rule is available for a given destructor function (in the
 manner described below) when it is the most recently added @(see enable)d
 @(':elim') rule for that function.</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
 @(see 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>")
other
(defxdoc emacs
  :parents (acl2-tutorial)
  :short "Emacs support for ACL2"
  :long "<p>Many successful users of ACL2 take advantage of the Emacs editor,
 for example by running ACL2 in an Emacs shell buffer.  If you do so, then you
 may wish to load the distributed file @('emacs-acl2.el') from one of two
 directories under the main ACL2 directory: @('books/emacs/') if you use a
 recent version of Emacs, or @('emacs/') if you use Emacs 24.  An easy way to
 arrange this is to put the load form into your @('.emacs') file; here,
 @('DIR') denotes your main ACL2 directory.</p>

 @({
 (load "DIR/books/emacs/emacs-acl2.el") ; for recent Emacs versions
 })

 <p><b>-OR-</b></p>

 @({
 (load "DIR/emacs/emacs-acl2.el") ; for Emacs 24
 })

 <p>The file begins with considerable comments describing what it offers.</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>")
other
(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 a call of @(tsee ENCAPSULATE), @(tsee PROGN), @(tsee PROGN!),
 or @(tsee INCLUDE-BOOK);</li>

 <li>@('x') is of the form @('(LOCAL 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 @('(SKIP-PROOFS x1)') where @('x1') is
 an embedded event form;</li>

 <li>@('x') is of the form @('(WITH-CBD str x1)'), where @('str') is a string
 and @('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 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') 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>For another use of @('make-event') to create embedded event forms, see
 @(see make-event-example-3).</p>

 <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>")
other
(defxdoc enable
  :parents (theories theory-functions)
  :short "Adds names to current theory"
  :long "@({
  Example:
  (enable fact (:e 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>

 <p>To see the runes currently disabled that are among those created when a
 function symbol @('FN') is introduced, evaluate @('(disabledp 'FN)').</p>")
other
(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))
 })")
other
(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))
 })")
other
(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 on return value.  As with all @(see events), a call of
 @('encapsulate') returns an @(see error-triple), @('(mv erp val state)'),
 where @('erp') is @('nil') when the event is redundant or is successfully
 admitted.  When @('erp') is @('nil'), the value @('val'), which is typically
 printed after a space, is determined as follows.</p>

 <ul>

 <li>If the @('encapsulate') event is @(see redundant), then @('val') is
 @(':redundant').</li>

 <li>Otherwise, if no new events are introduced, then @('val') is
 @(':empty-encapsulate').</li>

 <li>Otherwise, if the last sub-event in the final pass of the @('encapsulate')
 form evaluates to @('(mv nil '(:return-value x)')) for some @('x'), @('val')
 is @('x').  Note that this can be accomplished by placing the form
 @('(value-triple '(:return-value x) :on-skip-proofs t)') as the final form in
 the @('encapsulate'), but since proofs are skipped during that pass, the
 argument @(':on-skip-proofs t') is necessary for @('val') to be @('x').</li>

 <li>Otherwise, if the list of @(see signature)s is @('nil') then @('val') is
 @('t').</li>

 <li>Otherwise, if there is a single signature introducing the function symbol,
 @('fn'), then @('val') is @('fn').</li>

 <li>Otherwise, @('val') is the list of function symbols introduced in the list
 of signatures.</li>

 </ul>

 <p>Remark on implicit @(see constraint)s (unknown-constraints).  See @(see
 partial-encapsulate) for a related utility that allows some of the constraints
 to be unspecified.  This is an advanced capability that is useful when one
 installs special-purpose code, possibly in raw Lisp, using a trust tag (see
 @(see defttag)).</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>")
other
(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)")
other
(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>")
other
(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)")
other
(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)")
other
(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)")
other
(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)")
other
(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)")
other
(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>")
other
(defxdoc equality-variants
  :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 intersection$) ; (see Note below)
 @(tsee intersectp)
 @(tsee member)
 @(tsee no-duplicatesp)
 @('position-ac')
 @(tsee position)
 @(tsee put-assoc)
 @(tsee rassoc)
 @(tsee remove)
 @(tsee remove-assoc)
 @(tsee remove-duplicates)
 @(tsee remove1)
 @(tsee remove1-assoc)
 @(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>")
other
(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.
 })")
other
(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))
 })")
other
(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>")
other
(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)
  (er-soft  'top-level "Illegal-inputs" "Illegal inputs, ~x0 and ~x1." a b)
 })

 <p>The examples above all print an error message to standard output saying
 that (the values of) @('a') and @('b') are illegal inputs.  However, the first
 three &mdash; which we call <i>hard errors</i> &mdash; abort evaluation after
 printing an error message (while logically returning @('nil'), though in
 ordinary evaluation the return value is never seen); while the last two
 &mdash; so-called <i>soft errors</i> &mdash; return an @(see error-triple),
 @('(mv t nil state)'), after printing an error message.  The result in each of
 the two soft error cases 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 cause a hard 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 examples above expand to calls of ACL2
 functions; see below.  Also see @(see illegal), @(see hard-error), and @(see
 error1).  The @('hard?')/@('hard?!') forms have expansions that call the
 function @(tsee hard-error), which has a @(see guard) of @('T'), while the
 @('hard')/@('hard!') forms have expansions that call the function @(tsee
 illegal), which has a guard that is logically @('NIL').  Those generate code
 that is in @(':')@(tsee logic) mode, as do variants of @('(er soft ...)').
 The soft error forms expand to calls of the function @(tsee error1), which
 necessarily takes @(tsee state) as an explicit argument since it returns an
 @(see error-triple).  The guard for the soft error forms is that of @(tsee
 error1).  Note in particular that soft errors require the state to satisfy
 certain restrictions beyond just the usual @('state-p') predicate.</p>

 <p>The general forms of the macros are as follows.  Their macroexpansions
 include code that avoids the printing of error messages when error output is
 inhibited &mdash; see @(see set-inhibit-output-lst) &mdash; but here we show
 only the essential function calls.  Note that all arguments are evaluated even
 when error output is inhibited.</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 NIL FMT-STRING
              (LIST (CONS #\0 ARG1) (CONS #\1 ARG2) ... (CONS #\k ARGk)))

  (er-soft  ctx summary fmt-string arg1 arg2 ... argk)
    ==> {macroexpands, in essence, to:}
  (ERROR1     CTX SUMMARY 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>")
other
(defxdoc er-hard
  :parents (errors acl2-built-ins)
  :short "Print an error message and ``cause a hard error''"
  :long "<p>See @(see er) for relevant background, which is assumed below, and
 related utilities.</p>

 @({
 General Form:
 (er-hard context summary str &rest str-args)
 })

 <p>where context is a legal context (see @(see ctx)), @('summary') is @('nil')
 or a string, @('str') is a string, and @('str-args') are @('tsee fmt')
 arguments for @('str').  Note that @('(er-hard context summary str ...)') is
 equivalent to @('(er hard context (cons summary str) ...)').  The use of a
 non-@('nil') @('summary') allows suppression of this error message without
 suppressing all error output; see @(see set-inhibit-er).</p>

 <p>Calls of @('er-hard') expand much like calls @('(er hard ...)'), in the
 sense that both expand to calls of the function, @(tsee illegal), which has a
 @(see guard) equivalent to @('nil').  See @(see er-hard?) for a similar
 utility that avoids generating guard obligations.</p>

 <p>See @(tsee er-soft) for a similar utility pertaining to ``soft''
 errors.</p>")
other
(defxdoc er-hard?
  :parents (errors acl2-built-ins)
  :short "Print an error message and ``cause a hard error''"
  :long "<p>See @(see er-hard) for a nearly identical utility that is aligned
  with @('(er hard ...)'), generating a @(see guard) obligation of @('nil').
  By contrast, @('(er-hard? ...)') is aligned with @('(er hard? ...)')): these
  do not generate guard obligations.  This distinction is due to the fact that
  a call of @('(er-hard ...)') macroexpands to a call of the function, @(tsee
  illegal), while a call of @('(er-hard? ...)') macroexpands to a call of the
  function, @(tsee hard-error).</p>

 @({
 General Form:
 (er-hard? context summary str &rest str-args)
 })

 <p>Other than the difference in guard obligations generated, as discussed
 above, @('er-hard?') behaves identically to @('er-hard').  See @(see er-hard)
 and for relevant background, see @(see er).</p>")
other
(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 @('er-progn') form returns the value of the last 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>)))))))))
 })")
other
(defxdoc er-soft
  :parents (errors acl2-built-ins)
  :short "Print an error message and ``cause a soft error''"
  :long "<p>See @(see er) for relevant background, which is assumed below, and
 related utilities.</p>

 @({
 General Form:
 (er-soft context summary str &rest str-args)
 })

 <p>where context is a legal context (see @(see ctx)), @('summary') is @('nil')
 or a string, @('str') is a string, and @('str-args') are @('tsee fmt')
 arguments for @('str').  The use of a non-@('nil') @('summary') allows
 suppression of this error message without suppressing all error output; see
 @(see set-inhibit-er).</p>

 <p>See @(tsee er-hard) for a similar utility pertaining to ``hard''
 errors.</p>")
other
(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>In certain settings, notably when printing evaluation results, multiple
 values @('(mv erp val state)') may be considered an error triple even when
 @('val') is a @(see df) rather than an ordinary object.  Here is an example;
 see @(see df) for more about how floating-point numbers are simulated in
 ACL2.</p>

 @({
 ACL2 !>(mv nil (to-df 3) state)
  #d3.0
 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>")
other
(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>")
other
(defxdoc error1
  :parents (errors acl2-built-ins)
  :short "Print an error message and cause a ``soft error''"
  :long "<p>@('(Error1 ctx summary str alist state)') returns @('(mv t nil
 state)').  An error message is first printed using the ``context'' @('ctx'),
 as well as the string @('str') and alist @('alist') that are of the same kind
 as expected by @(tsee fmt) &mdash; unless error output is inhibited
 (see @(see set-inhibit-output-lst) and @(see with-output)) or @('summary') is
 non-@('nil'), in which case it is a string, and error output of that type is
 inhibited (see @(see set-inhibit-er)).  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).  However, @('error1')
 is a guard verified @(tsee logic) mode function whose guard is</p>

 @({
 (AND (STATE-P STATE)
      (STRINGP STR)
      (ERROR1-STATE-P STATE)
      (CHARACTER-ALISTP ALIST)
      (OR (NULL SUMMARY) (STRINGP SUMMARY)))
 })

 <p>Note in particular that the state must not only satisfy the basic
 recognizer, @('state-p'), for ACL2 states but must also satisfy
 @('error1-state-p'), which includes additional restrictions ensuring that
 @('error1') can print formatted output to the standard character output
 channel, @(tsee standard-co), interpret the table maintained by @(tsee
 set-inhibit-er), etc.  If the complexity of @(see error1)'s guard discourages
 you from using it in guard-verified logic mode systems you may wish to cause a
 @(see hard-error) with @(tsee illegal) or the more unified way of signaling
 errors with the macro @(tsee er).</p>

 <p>As mentioned above, @('error1') always returns @('(mv t nil state)').  But
 if a call @('(error1 ctx summary str alist)') is encountered during
 evaluation, then unless output is inhibited as described above, 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 !>
 })")
other
(defxdoc errors
  :parents (programming)
  :short "Support for causing runtime errors, breaks, assertions, etc.")
other
(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 ACL2 loop (see
 @(see lp)).  (A potentially unsound exception is raw-mode; 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 @(':q'), submit the
 desired forms to the Common Lisp read-eval-print loop, and reenter ACL2 with
 @('(lp)').  WARNING: Doing so is potentially unsound; see @(see q).</p>")
other
(defxdoc ev$
  :parents (apply$)
  :short "Evaluate a tame expression using @('apply$')"
  :long "<p>When @(tsee apply$), actually @(tsee apply$-lambda), is asked to
  apply a @('LAMBDA') object to some arguments it calls @('ev$') on the body of
  the object and an alist binding the formals of the object to the arguments.
  Roughly put, @('ev$') ``works'' by looking up symbols, returning quoted
  objects, and using @('apply$') to apply function symbols to the results of
  evaluating their arguments.  @('Ev$') and its clique-mate @('ev$-list') are
  mutually-recursive with @('apply$').  @('Ev$') can only evaluate ``as
  expected'' on @(see tame) expressions and requires @(tsee warrant)s, explicit
  in the proof theory or implicit in the evaluation theory, to determine @(see
  badge)s and thus tameness.  See @(tsee apply$) for details, including the
  formal definitions of @('ev$') and @('ev$-list').  For a summary of how the
  rewriter handles @('apply$'), @('ev$'), and @('loop$') @(see scion)s, see
  @(see rewriting-calls-of-apply$-ev$-and-loop$-scions).</p>")
other
(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>")
other
(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 any
 @(see meta-extract) functions in the rule or any @(tsee defaxiom) events, 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, including the notion of one function symbol being &ldquo;ancestral
 in&rdquo;, also expressed as &ldquo;an ancestor of&rdquo;, in another function
 symbol.</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 @(see
 meta-extract) functions if they are used in the proposed @(':meta')
 theorem.</p>

 <p>These requirements 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 (NOT (CONSP X))
                    (NOT (SYMBOLP X)))
               (EQUAL (EVL2 X A) NIL)))
    (DEFTHM EVL2-CONSTRAINT-7
      (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-8
      (IMPLIES (AND (CONSP X) (EQUAL (CAR X) 'F2))
               (EQUAL (EVL2 X A)
                      (F2 (EVL2 (CADR X) A)))))
    (DEFTHM EVL2-CONSTRAINT-9
      (IMPLIES (AND (CONSP X) (EQUAL (CAR X) 'G))
               (EQUAL (EVL2 X A) (G))))
    (DEFTHM EVL2-CONSTRAINT-10
      (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) or
 @(tsee apply$) &mdash; more specifically, @(see warrant)s &mdash; 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>Here is an example that doesn't use @(tsee defattach) explicitly, but uses
 @(see warrant)s, which essentially have attachments so that every call of a
 warrant evaluates to @('T').  As for the preceding example, these events
 succeed if we remove the restriction stated above about common ancestors of
 the evaluator and the meta or clause-processor function.</p>

 @({
 (in-package "ACL2")

 (include-book "projects/apply/top" :dir :system)

 (defevaluator evl evl-list
   ((apply$ fn args)))

 (encapsulate
   ()
   (local (defun$ f () (declare (xargs :guard t)) t))
   (local (defun my-meta-fn (x)
            (if (and (equal x '(apply$ 'f 'nil))
                     (apply$-warrant-f))
                *t*
              x)))
   (local (defthm my-meta-fn-correct
            (equal (evl x a)
                   (evl (my-meta-fn x) a))
            :rule-classes ((:meta :trigger-fns (apply$)))))
   (defthm unwarranted-fact-about-quote-f
     (equal (apply$ 'f nil) t)
     :rule-classes nil))

 (defun$ f () nil)

 (defthm apply$-warrant-f-false
   (not (apply$-warrant-f))
   :hints (("Goal" :use unwarranted-fact-about-quote-f))
   :rule-classes nil)

 ; But apply$-warrant-f is a function with no non-trivial constraint.

 (defthm contradiction
   nil
   :hints
   (("Goal"
     :use (:functional-instance
           apply$-warrant-f-false
           (apply$-warrant-f (lambda () t))
           (apply$-userfn (lambda (fn args) nil))
           (badge-userfn (lambda (fn) '(APPLY$-BADGE 0 1 . 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>

 <p>One can sometimes work around this restriction; see @(see
 transparent-functions).</p>")
other
(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)")
other
(defxdoc evens
  :parents (lists acl2-built-ins)
  :short "The even-indexed members of a list"
  :long "<p>The call @('(evens x)') returns the restriction of the true-list
 @('x') to its even-indexed members (with zero-based indexing).  Note that if
 @('x') is a list @('(k1 a1 k2 a2 ... kn an)') that satisfies the predicate
 @(tsee keyword-value-listp), then @('(evens x)') lists the keys @('ki') of
 @('x').  Thus, the following is a theorem.</p>

 @({
  (thm (iff (keyword-value-listp l)
            (and (true-listp l)
                 (evenp (len l))
                 (keyword-listp (evens l))))
       :hints (("Goal" :induct (keyword-value-listp l))))
 })

 @(def evens)")
other
(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 @(see
 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>")
other
(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 !>
 })

 <p>The examples above illustrate how the @('evisc-table') is used when
 printing evaluation results.  More generally, that @(see table) is used when
 @(tsee fmt) (or a related function such as @(tsee fms)) prints an object using
 @('~x') @('~X'), @('~y'), @('~Y'), @('~f'), or @('~F').</p>")
other
(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>")
other
(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>")
other
(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))))).
 })")
other
(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))))).
 })")
other
(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>")
other
(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)))).
 })")
other
(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))))).
 })")
other
(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 ensure 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)).
 })")
other
(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 ensure 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>")
other
(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>")
other
(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>")
other
(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>

 @({
  Example:
  (:executable-counterpart length)
 })

 <p>which may be abbreviated in @(see theory) expressions in either of the
 following two ways (see @(see rune)).</p>

 @({
  (:e length)
  (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>")
other
(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>")
other
(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>")
other
(defxdoc exit
  :parents (good-bye)
  :short "Quit entirely out of Lisp"
  :long "<p>Same as @(tsee good-bye).</p>")
other
(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>")
other
(defxdoc explain-giant-lambda-object
  :parents (apply$)
  :short "print data related to a large lambda object"
  :long "<p>Translate will signal an error if it encounters an
  &ldquo;excessively large&rdquo; @(tsee lambda) object.  These objects are so
  large they are difficult to comprehend when printed.  So the error message
  directs you to this documentation topic.  To see the @('lambda') object that
  caused the error, execute</p>

  @({
  (explain-giant-lambda-object)
  })

  <p>The rest of this documentation topic explains why we detect these objects
  and what you can do about them.</p>

  <p>When a @(tsee lambda) object is translated we @(tsee hons-copy) it
  so that it is uniquely represented.  This speeds up the performance of the
  compiled @('lambda') cache (see @(tsee print-cl-cache)).</p>

  <p>However, if the number of conses in the @('lambda') object is greater than
  or equal to @('(lambda-object-count-max-val)'), we cause an error.  If this
  error has been signaled in your session we recommend that you evaluate
  @('(explain-giant-lambda-object)'), which will tell you more about the
  excessively large @('lambda') object.  The current value of
  @('(lambda-object-count-max-val)') is 200,000.  For reference, the largest
  function definition in the ACL2 sources (as of Version  8.6) is the @(tsee
  mutual-recursion) event defining @('rewrite') and its 51 mutually recursive
  subfunctions.  The total number of conses in that clique is 14,656.</p>

  <p>There are generally two ways excessively large @('lambda') objects come
  into existence: (1) they are generated automatically, as by macros,
  functions, or @(tsee make-event), or (2) you wrote a small @('lambda') object
  but used a big quoted constant in it.</p>

  <p>(1) If the offending @('lambda') object was built mechanically, we
  recommend that you redefine the generation process so that it introduces a
  named function.  For example, suppose the @('lambda') object sketched below
  is excessively large.</p>

  @({
  (lambda (x y)
    (if (eq x 'FOO1)
        (my-foo1 y)
        (if (eq x 'FOO2)
            (my-foo2 y)
            ...)))
  })

  <p>Then perhaps instead of generating that object you could generate
  the definition</p>

  @({
  (defun my-big-switch (x y)
    (if (eq x 'FOO1)
        (my-foo1 y)
        (if (eq x 'FOO2)
            (my-foo2 y)
            ...)))
  })

  <p>And then use the quite small @('(lambda$ (x y) (my-big-switch x y))') in
  place of the offending @('lambda') object.  Of course, this is not always
  easy to carry out, since it would also require calling @(tsee defwarrant) on
  @('my-big-switch') and providing that warrant as a hypothesis to any theorem
  involving the new @('lambda') object.</p>

  <p>(2) If the offending @('lambda') object just contains large quoted
  constants perhaps you can bind a variable to the large value outside of the
  @('lambda') object and pass that variable into the @('lambda') object in a
  new formal.</p>

  <p>For example, suppose the term @('(regression-suite)') returns is a list of
  pairs of sample inputs and correct output for testing some software system
  whose binary machine code is in the constant declared below.</p>

  @({
  (defconst *system*
    '(#x488b55f0
      #x31ff
      #xff142570081050
      #xf84995b0000
      #xf645f801
      #xf8573100000
      #x807df019
      ...))
  })

  <p>Then we might wish to execute something like the following.</p>

  @({
  ACL2 !>(loop$ for pair in (regression-suite)
                always (equal (sim *system* (car pair)) (cdr pair)))
  })

  <p>which simulates the @('*system*') on every input in the regression suite
  and compares the result to the known correct answer.</p>

  <p>The formal translation of this term is</p>

  @({
   (always$ '(lambda (loop$-ivar)
               (equal (sim '(#x488b55f0
                             #x31ff
                             #xff142570081050
                             #xf84995b0000
                             #xf645f801
                             #xf8573100000
                             #x807df019
                             ...)
                           (car loop$-ivar))
                      (cdr loop$-ivar)))
            (regression-suite))
  })

  <p>Note that the constant @('*system*') has been rendered as its quoted value
  and that it is inside of the @('lambda') object.  If @('*system*') is a very
  large constant, that @('lambda') object may be excessively large.</p>

  <p>But we can avoid that by writing this instead.</p>

  @({
  ACL2 !>(let ((sys *system*))
           (loop$ for pair in (regression-suite)
                  always (equal (sim sys (car pair)) (cdr pair))))
  })

  <p>which essentially translates to</p>

  @({
  (let ((sys '(#x488b55f0
               #x31ff
               #xff142570081050
               #xf84995b0000
               #xf645f801
               #xf8573100000
               #x807df019
               dots)))
    (always$+ '(lambda (loop$-gvars loop$-ivars)
                 (equal (sim (car loop$-gvars)
                             (car (car loop$-ivars)))
                        (cdr (car loop$-ivars))))
              (list sys)
              (loop$-as (list (regression-suite)))))
  })

  <p>Note that the @('lambda') object no longer contains the large constant.
  It now refers to a &ldquo;global&rdquo; variable whose value is that of
  @('*system*').  The @('lambda') object is quite small.</p>

  <p>For what it is worth, the largest single object in the ACL2 image (as of
  Version  8.6) is the value of @('(w state)'), the logical world.  Upon
  starting the system @('(w state)') contains 128,784 elements, but contains
  multiple pointers to shared substructures (e.g., to tails of itself).  The
  total number of conses is on the order of @('(expt 10 655)') when counted
  naively, but the total number of distinct conses is 1,875,653.  So if you
  build a @('lambda') object containing the value of @('(w state)') it will be
  &ldquo;excessively large.&rdquo;</p>")
other
(defxdoc explain-near-miss
  :parents (debugging)
  :short "show why a rule's pattern and the :target do not match"
  :long "<p>When a near miss break occurs (see @(tsee monitor)) the user
  sees a message like this:</p>

  @({
  (1 Breaking (:REWRITE LEMMA) on (F (G A B) A '(A B C D ...)):

  The pattern in this rule failed to match the target.  However, this
  is considered a NEAR MISS under the break criteria,
  (:CONDITION 'T :ABSTRACTION ...), specified when this rule was
  monitored.  The following criterion is satisfied.

  * The :ABSTRACTION pattern provided in your monitor, ...,
  matches :TARGET.
  })

  <p>It can be difficult to determine why the pattern of the rule, e.g., the
  @(':lhs') of a @(':rewrite') rule, fails to match the @(':target') term,
  especially when large terms, large quoted constants, and @('lambda')
  expressions are involved.</p>

  <p>Included among the @(':')@(tsee brr-commands) is the @(':explain-near-miss')
  command which is intended to help explain.  This command can only operate in
  a near miss break.  If called in another context an error may occur.</p>

  <p>But in a near miss break, the situation is as follows.  The prover has
  tried to apply a rule that has been monitored with a break criterion meaning
  ``cause an interactive break when the target term (the term to currently
  being rewritten) satisfies this criterion but the triggering pattern of the
  rule fails to match the target term.''  When inside the resulting break, the
  target term is given by the @(tsee brr) command @(':target').  The
  ``triggering pattern'' of the rule in question depends on how the rule was
  stored (see @(tsee rule-classes)).  The triggering pattern of a @(':')@(tsee
  rewrite) rule &mdash; the most common class of rule &mdash; is the left-hand
  side of the concluding equality and can be obtained from within the break by
  typing the @(tsee brr) command @(':lhs').  The triggering pattern for a
  @(':')@(tsee rewrite-quoted-constant) rule is its right-hand side, but as
  explained in @(tsee rewrite-quoted-constant), the @('brr') command @(':lhs')
  will display it.  The triggering pattern for a @(':')@(tsee linear) rule is
  displayed by the @(':')@('max-term') @('brr') command.  The question the user
  will typically ask in this situation is ``why doesn't the triggering pattern
  match the target?''</p>

  <p>To understand the answer you have to understand how the ACL2 matching
  algorithm works.  The matching algorithm is given two terms, @('t1') and
  @('t2'), and attempts to find a substitution @('s') on the variables in
  @('t1') such that when @('t1') is instantiated with @('s') the result is
  @('t2'), i.e., @('t1/s') = @('t2').  Note that only the variables in the
  pattern, @('t1'), can be instantiated by @('s'').  In the case of a near miss
  break, no such substitution was found.</p>

  <p>The @(':explain-near-miss') command reruns the matching algorithm on the
  triggering pattern and the target, expecting failure and collecting
  information about where the failure occurred.  The output is intended to be
  self-explanatory.</p>

  <p>The message displays the pattern in question and the target term, but it
  also displays a version of the pattern in which the first unmatchable subterm
  is replaced by the expression @('<pat>').  That @('<pat>') is displayed
  in lowercase whereas the rest of the pattern and target are in uppercase.
  It marks where the matching broke down.</p>

  <p>The message goes on to show the mismatched subterms from the pattern and
  the target, the substitution that was computed to match everything up to
  @('<pat>') and what the @('<pat>') subterm of the pattern is when
  instantiated with that substitution.</p>

  <p>So, for example, suppose the rule's @(':lhs') and the current @(':target')
  are as shown below.  Then here is what @(':explain-near-miss') would
  print.</p>

  @({
  The ACL2 match algorithm attempted to match :LHS with :TARGET by finding
  a substitution, s, such that :LHS/s = :TARGET.  That attempt failed
  when trying to match the subterm of :LHS marked <pat> in :LHS' below.

  :LHS:      (F X (G X Y) (H X))
  :LHS':     (F X (G <pat> Y) (H X))
  :TARGET:   (F A (G B A) (H A))

  Below we show the substitution, s, computed prior to the failure; the
  subterm of :LHS we're calling <pat>; the instantiated subterm, <pat>/s;
  and the corresponding subterm, <tar>, of :TARGET.

  s:       ((X A))
  <pat>:   X
  <pat>/s: A
  <tar>:   B

  For the rewriter to get past this failure the match algorithm must
  be able to extend substitution s to s' so that <pat>/s' is equal to
  <tar> and our match algorithm could not find such an extension.
  })

  <p>Note that the substitution @('s') binds @('X') to @('A') to match the
  first argument of the @('F')-expression in the @(':LHS') to the corresponding
  argument in the @(':TARGET').  Then it tries to match @('(G X Y)') with @('(G
  B A)').  It fails on the first argument of that subterm, where @('<pat>') is
  shown in @(':LHS''), because @('X') has been bound to @('A') and @('A') and
  @('B') are different.  (Remember: only the variables of the pattern can be
  bound by the substitution.)</p>

  <p>When @('<pat>') and its corresponding subterm @('<tar>') are ``large'' but
  unequal quoted constants or @('lambda') expressions, @(':explain-near-miss')
  will call @(tsee compare-objects) on those objects.  It can be hard to spot
  how two large constants differ and @('compare-objects') points out the
  differences between two @('cons') trees.  @(':Explain-near-miss') considers
  an object ``large'' if the number of conses in it is 30 or greater.</p>

  <p>The command @(':explain-near-miss+') is like @(':explain-near-miss')
  except it never eviscerates any term and runs @('compare-objects') whenever
  the failure is on two distinct quoted objects or @('lambda') expressions
  regardless of their sizes.</p>

  <p>But note that @('compare-objects') is not run by either version of
  @('explain-near-miss') when the failure is of the most common kinds:</p>

  <ul>

  <li>(a) a variable in the pattern has already been bound in the
  substitution (i.e., bound earlier in the matching process) to a term that is
  not identical to the corresponding term in the target, or</li>

  <li>(b) a term in the pattern has a different function symbol than the
  corresponding term the target.</li>

  </ul>

  <p>So do not expect the @('compare-objects') output to appear often!</p>")
other
(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)")
other
(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)")
other
(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)")
other
(defxdoc extend-pathname
  :parents (io acl2-built-ins)
  :short "Extend a relative pathname to an absolute pathname"
  :long "<p>@('Extend-pathname') is a @(':')@(tsee program) mode function that
 takes a directory name as specified below and a filename (a string), and
 returns a corresponding pathname for the given file that is relative to the
 specified directory.  If the filename is already an absolute pathname then the
 return value is that filename, unchanged.</p>

 @({
 General Form:

 (extend-pathname dir filename state)
 })

 <p>where @('dir') is either a string, representing an absolute pathname for a
 directory, or a keyword, representing a project directory (see @(see
 project-dir-alist)); filename is a string representing a relative or absolute
 pathname; and @('state') is the ACL2 @(see state).</p>

 <p>The following examples illustrate the behavior of @('extend-pathname').</p>

 @({
 Examples (comments added)

 ACL2 !>(extend-pathname "~/temp" "foo.lisp" state)
 ; where the user is "bubba" here and in the remaining examples
 "/home/bubba/temp/foo.lisp"
 ACL2 !>(extend-pathname "~/temp/" "foo.lisp" state)
 ; the final / is optional for the directory name
 "/home/bubba/temp/foo.lisp"
 ACL2 !>(extend-pathname "~/temp/" "no-such-file" state)
 ; name of non-existent file is still extended
 "/home/bubba/temp/no-such-file"
 ACL2 !>(extend-pathname "." "no-such-file" state)
 ; THIS IS NOT SUPPORTED, because the first argument is a relative pathname,
 ; not an absolute pathname; but in this case a reasonable answer happens to
 ; be provided.  See the next example for how to do this properly.
 ; Here we assume that the current working directory is "/home/joe"
 "/home/joe/no-such-file"
 ACL2 !>(extend-pathname (canonical-pathname "." t state) "no-such-file" state)
 ; As above, but the first argument is first turned into an absolute pathname,
 ; which makes the call a supported one.
 "/home/joe/no-such-file"
 ACL2 !>(extend-pathname (cbd) "no-such-file" state)
 ; assumes that the connected book directory (see :DOC cbd) is "/data/santa"
 "/data/santa/no-such-file"
 ACL2 !>(extend-pathname :system "no-such-file" state)
 ; assumes that system books directory is "/data/acl2/books"
 "/data/acl2/books/no-such-file"
 ACL2 !>(extend-pathname "/data/acl2" "~/temp/foo.lisp" state)
 ; directory is ignored when filename is already absolute
 "/home/bubba/temp/foo.lisp"
 ACL2 !>(extend-pathname :system "~/temp/foo.lisp" state)
 ; directory is ignored when filename is already absolute
 "/home/bubba/temp/foo.lisp"
 })

 <p>Note that when the indicated file exists, @('extend-pathname') resolves
 symbolic links by using @(tsee canonical-pathname).  If you don't want
 symbolic links to be resolved there are simpler alternatives; for example, see
 @(see oslib::catpath).</p>")
other
(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)
 })

")
other
(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>")
other
(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>To test your extended metafunctions outside of proof attempts, see @(see
 trust-mfc).</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 @(see 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))))
 })")
other
(defxdoc extra-info
  :parents (guard)
  :short "Sources of measure, guard, or constraint 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.  See @(see
 set-constraint-tracking) to see how @('extra-info') can help in debugging
 failures to prove constraint obligations generated by
 @(':functional-instance') @(see hints) (see @(see lemma-instance)).</p>")
other
(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>

 <p>Click <see topic='@(url symbols)'>here</see> <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> for an explanation of conversion of
 symbols to upper case.</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>
 (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>")
other
(defxdoc f-boundp-global
  :parents (programming-with-state acl2-built-ins)
  :short "Check whether a global variable in @(tsee state) has a value"
  :long "@({
  Examples:
  (f-boundp-global 'y state)

  General Form:
  (f-boundp-global s state)
 })

 <p>where @('s') evaluates to a symbol.  Note that this executes more
 efficiently when @('s') is a constant of the form @(''sym').</p>

 <p>This value returned is @('t') or @('nil') according to whether a value is
 assigned to the given symbol in the ACL2 @(see state).  Also see related
 utilities @(tsee f-get-global), @(tsee f-put-global), and @(tsee
 makunbound-global).</p>")
other
(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>")
other
(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>")
other
(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)))
 })")
other
(defxdoc failure
  :parents (debugging)
  :short "How to deal with a failure to admit an event"
  :long "<p>There are many reasons why an event can fail to be admitted.
 Generally, an error message will explain the failure, sometimes pointing to
 documentation that is specific to the relevant issue.  There are tools that
 can sometimes help: for example, to debug failures of @(tsee encapsulate) or
 @(tsee progn) events, as well as @(tsee certify-book) failures, see @(see
 redo-flat).</p>

 <p>However, proof failures are typically not as trivial to debug as, for
 example, syntactic errors (such as spelling errors in the name of a function).
 Fortunately, ACL2 offers a variety of techniques for dealing with proof
 failures, and some are discussed below.  Also see relevant subtopics of the
 topic, @(see debugging).  Some frequently-used tools for proof debugging that
 are discussed in those subtopics include @(see accumulated-persistence), @(see
 break-rewrite), @(see with-brr-data), @(see cgen), and @(see proof-builder).
 Also see @(see nil-goal) for ideas about how to proceed when the prover
 generates a goal of @('NIL').</p>

 <p>We turn now to the problem of dealing with proof failures.</p>

 <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 @(see 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 pso), @(see
 set-gag-mode), and @(see proof-tree).  System hackers may want to consider
 using the utility, @(tsee checkpoint-list).</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>")
other
(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>In the rare case that you need to have the sequence @('"""}') in your
string, you can instead use @('"""\}').  If you need to have the sequence
@('"""\}'), you can use @('"""\\}').  In general, when a substring
contains three doublequotes followed by 1 or more backslashes and a right
curlybrace, it just removes one of the backslashes.</p>")
other
(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>")
other
(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>")
other
(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>

 ")
other
(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>")
other
(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>When the host Lisp is CCL or SBCL, the associated hash table may be freed
 up automatically by the garbage collector when the corresponding alist is no
 longer referenced.  (To trigger garbage collection manually, see @(see gc$).)
 But for Lisp implementations other than CCL and SBCL this is not the case so,
 to avoid memory leaks, you should use @('fast-alist-free') to free up
 associated hash tables 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)")
other
(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>")
other
(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)")
other
(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)")
other
(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>")
other
(defxdoc fast-cert
  :parents (certify-book include-book)
  :short "A mode for faster, but possibly unsound, book certification"
  :long "<p>See @(see certify-book) and @(see include-book) for background on
 certifying and including @(see books).</p>

 <p>By default, @(tsee certify-book) includes a &ldquo;Step 3&rdquo; that does
 a @(see local-incompatibility) check.  That check can be expensive for some
 &ldquo;industrial-size&rdquo; books if there are @(see local) events early in
 the book or in its @(see portcullis) commands.  Fast-cert mode provides a way
 to avoid the @(see local-incompatibility) check.  There are the following two
 drawbacks to using ACL2 with fast-cert mode enabled (as described further
 below).</p>

 <ul>

 <li>It may be unsound!  See Section &ldquo;Unsoundness&rdquo; below.</li>

 <li>Therefore, after a book is certified with fast-cert mode enabled, then any
 subsequent attempt to include that book will consider it to be uncertified
 unless the @(tsee include-book) event is executed with fast-cert mode enabled.
 See Section &ldquo;Effects of fast-cert mode...&rdquo; below.</li>

 </ul>

 @({
 Example Forms:

 (set-fast-cert t state)       ; enter fast-cert active mode
 (set-fast-cert nil state)     ; disable fast-cert mode
 (set-fast-cert :accept state) ; enter fast-cert accept mode

 General Form:

 (set-fast-cert expr state)
 })

 <p>where if @('expr') evaluates to @('val'), then: if @('val') is @('t') then
 fast-cert mode becomes (or remains) active; if @('val') is @('nil'), then
 fast-cert mode becomes (or remains) disabled; and otherwise @('val') must be
 @(':accept').  In the last case, ACL2 behaves as though fast-cert mode is
 disabled &mdash; we also say ``not enabled'' for ``disabled'' &mdash; but
 books can be considered certified even if they were certified with fast-cert
 mode enabled.  We say more about these three modes in Section &ldquo;Fast-cert
 modes&rdquo; below.</p>

 <p>Another way to enter fast-cert mode is to set environment variable
 @('ACL2_FAST_CERT') to a non-empty value before starting ACL2.  The
 case-insensitive value, @('"accept"'), causes @('(set-fast-cert :accept
 state)') to be evaluated at startup; otherwise, a non-empty value causes
 @('(set-fast-cert t state)') to be evaluated at startup.</p>

 <p>We turn now to sections that include those promised above.</p>

 <h3>Fast-cert modes</h3>

 <p>There are the following fast-cert modes.</p>

 <ul>

 <li><b>Active</b>: entered with @('(set-fast-cert t state)').  When ACL2 is in
 this mode, the @(see local-incompatibility) check is skipped when certifying a
 book, and the book's @(see certificate) marks it as a &ldquo;fast-cert
 book&rdquo;.</li>

 <li><b>Disabled</b>: entered with @('(set-fast-cert nil state)'), though this
 is the default mode.  In this mode the usual @(see local-incompatibility)
 checks are performed during book certification, and every fast-cert book (as
 defined just above) is considered to be uncertified.</li>

 <li><b>Accept</b>: entered with @('(set-fast-cert :accept state)').  When ACL2
 is in this mode, @(see local-incompatibility) checks are performed just as
 when fast-cert mode is disabled, but a fast-cert book is treated as certified
 just like any other book.</li>

 </ul>

 <p>Fast-cert mode is considered to be &ldquo;enabled&rdquo; exactly when it is
 not disabled, that is, when fast-cert mode is active or accept.</p>

 <p>The discussion above leaves open the question of whether a book that is
 certified in accept mode is marked as a fast-cert book.  That happens only if
 at least one fast-cert book has been included during the session, either
 before the book's certification began or during evaluation of the book's
 events.</p>

 <p>It is always legal to change fast-cert mode from disabled to enabled (using
 @('set-fast-cert')).  It is legal to change fast-cert mode from enabled to
 disabled provided there has been no attempt during the session to include a
 fast-cert book while fast-cert mode is enabled.</p>

 <h3>Potential for unsoundness</h3>

 <p>Consider the proof of @('nil') constructed by the following two books.</p>

 @({
 ;;; fast-cert-unsound-sub.lisp
 (in-package "ACL2")
 (local (defun f () t))
 (defun g () (f))
 (defthm g-is-t
   (equal (g) t))

 ;;; fast-cert-unsound.lisp
 (in-package "ACL2")
 (defun f () nil)
 (include-book "fast-cert-unsound-sub")
 (thm nil
      :hints (("Goal" :use g-is-t)))
 })

 <p>Now execute the following commands to prove @('nil')!</p>

 @({
 (set-fast-cert t state)
 (certify-book "fast-cert-unsound-sub")
 :u
 (certify-book "fast-cert-unsound")
 })

 <p>To see what went wrong, consider what happens if we try this without first
 evaluating @('(set-fast-cert t state)').  In that case, we can see that an
 attempt to certify @('"fast-cert-unsound-sub"') fails the @(see
 local-incompatibility) check.</p>

 @({
 * Step 3:  That completes the admissibility check.  Each form read
 was an embedded event form and was admissible.  We now retract back
 to the initial world and try to include the book; see :DOC
 local-incompatibility.


 ACL2 Error [Translate] in ( DEFUN G ...):  The symbol F (in package
 "ACL2") has neither a function nor macro definition in ACL2.  Please
 define it.  See :DOC near-misses.  Note:  this error occurred in the
 context (F).
 })

 <p>That is, the attempt in Step 3 to include
 @('"fast-cert-unsound-sub.lisp"') fails the local-incompatibility check
 because the definition of @('f') is @(see local), hence skipped, so the
 definition of @('g') is illegal.  Without the use of fast-cert mode, the
 local-incompatibility check would catch this problem.</p>

 <p>(Technical note: if the book is certified while fast-cert mode is active,
 then when we subsequently include @('"fast-cert-unsound-sub"') when
 fast-cert mode is enabled, there is &mdash; perhaps surprisingly &mdash; no
 error.  That is because the translation (see @(see term)) of the definition of
 @('g') is cached in the book's @(see certificate).)</p>

 <p>Note that unsoundness can occur even when fast-cert is in accept mode, not
 just in active mode.  That's because one may include a book in accept mode
 that was certified in a previous session while fast-cert was in active mode,
 and that book could prove @('nil') as in the example above.  In short,
 unsoundness can occur when fast-cert mode is enabled (i.e., fast-cert is in
 accept or active mode).</p>

 <p>Unsoundness when fast-cert mode is enabled is probably rare in practice.
 But because unsoundness is possible with fast-cert mode enabled, a
 &ldquo;@('TTAG NOTE')&rdquo; message is printed when fast-cert mode is
 enabled, for example as follows when fast-cert mode transitions from disabled
 to active.</p>

 @({
 ACL2 !>(set-fast-cert t state)

 TTAG NOTE: Fast-cert mode is active (see :DOC fast-cert).
  T
 ACL2 !>
 })

 <p>The message above may seem a bit misleading, since there is no actual trust
 tag (ttag) involved.  The &ldquo;@('TTAG NOTE')&rdquo; message is simply
 ACL2's way of conveying that there is a trust issue &mdash; typically with the
 use of @(tsee defttag) but also when entering fast-cert mode.</p>

 <p>We conclude this section by mentioning other potential sources of
 unsoundness when fast-cert mode is enabled.  There are probably yet others,
 but again, it is probably rare for fast-cert mode to exhibit unsoundness.
 These behaviors are due to avoiding the @(see local-incompatibility) check
 during certification when fast-cert mode is active.</p>

 <ul>

 <li>Hidden @(tsee defpkg) events are not recorded in a book's @(see
 certificate) when fast-cert mode is active.  See @(see
 hidden-death-package).</li>

 <li>Information about sub-books that is normally recorded in a @(see
 certificate), including the @(see book-hash) values in the @(see portcullis)
 and the @(see keep), is omitted by certification when fast-cert mode is
 active.  This prevents ACL2 from noticing when sub-books are uncertified or
 have changed since the time of the parent book's certification.</li>

 </ul>

 <p>Here are some necessary checks that may be omitted when the
 local-incompatibility check is skipped.</p>

 <ul>

 <li>A non-local @(see congruence) rule needs its alleged equivalence relation
 to be an equivalence relation non-locally.  Generally this means that the
 supporting @(tsee defequiv) event must be non-local.</li>

 <li>A non-local rule of class @(':')@(tsee meta) or @(':')@(tsee
 clause-processor) needs its evaluators to be evaluators non-locally.</li>

 <li>A @(tsee defattach) event imposes requirements on function symbols to be
 @(see guard)-verified.  So if a @('defattach') event is non-local, each
 necessary guard verification status must hold non-locally.</li>

 </ul>

 <p>Because of potential unsoundness when fast-cert mode is enabled, especially
 as explained in the item above regarding status of books that are included in
 a parent book, it is strongly recommended that you eventually certify your
 collection of books with fast-cert mode disabled.  Otherwise there is no sort
 of guarantee that your proofs are valid!</p>

 <h3>Interactions involving fast-cert mode</h3>

 <ul>

 <li>When a book is successfully certified with fast-cert mode active, its
 @(see certificate) records this fact.  Let's call such a certificate (or book)
 a &ldquo;fast-cert certificate&rdquo; (or &ldquo;fast-cert book&rdquo;);
 otherwise it is a &ldquo;normal&ldquo; certificate (or &ldquo;normal
 book&rdquo;).</li>

 <li>When a book is successfully certified with fast-cert in accept mode, the
 book is a normal book only if no fast-cert book is included before or during
 certification.</li>

 <li>When @('include-book') is performed on a book with a valid fast-cert
 certificate, that book is considered to be certified if fast-cert mode is
 enabled and otherwise is considered to be uncertified.</li>

 <li>When @('include-book') is performed on a book with a valid normal
 certificate, that book is considered to be certified regardless of whether or
 not fast-cert mode is enabled at @('include-book') time.</li>

 <li>When @(see provisional-certification) is used during @('certify-book')
 while fast-cert mode is active, then fast-cert is treated as being in accept
 mode; in particular, the local-incompatibility check) is performed in the
 normal way.</li>

 <li>Normally @('certify-book') warns about functions that have not had their
 @(see guard)s verified.  This message is suppressed when fast-cert mode is
 active, because local @('include-book') forms in the certification world can
 make that message very long.</li>

 <li>When a fast-cert book is included while fast-cert mode is enabled, then
 the rest of that ACL2 session must have fast-cert mode enabled.  This
 restriction guarantees that any book then certified during that session will
 be given a fast-mode certificate.</li>

 <li>It is illegal to call @('set-fast-cert') during @('make-event') expansion
 (see @(see make-event)).  There is also an explicit check to prohibit calls of
 @('set-fast-cert') during @('certify-book'), though that is probably
 unnecessary because of the @('make-event') restriction unless that restriction
 is subverted using a trust tag.</li>

 </ul>

 <p>See @(see fast-cert-anomalies) for some possibly surprising (and more
 obscure) consequences of using fast-cert mode.</p>

 <h3>Fast-cert mode and @(tsee save-exec)</h3>

 <p>The motivation for adding fast-cert mode was to provide faster
 certification based on executables created with @(tsee save-exec).  We
 illustrate with an example, which starts by @(see local)ly including a book
 that brings in many definitions and rules (it may take about a minute to
 include) and then saving an executable.  The initial (non-local)
 @('include-book') forms below might not be necessary for all uses of the
 executable.</p>

 @({
 (include-book "centaur/sv/portcullis" :dir :system)
 (include-book "std/util/define" :dir :system)
 (local (include-book "centaur/sv/top" :dir :system))
 :q
 (save-exec "sv-top" "Locally includes centaur/sv/top")
 })

 <p>Now suppose we want to create a book that is based on a tiny part of what
 is provided by the book included above, as follows (comments omitted
 here).</p>

 @({
 (in-package "SV")

 (define name-p (x)
   :parents (name)
   (or (stringp x)
       (integerp x)
       (eq x :self)
       (and (consp x)
            (eq (car x) :anonymous))))

 (define name-fix ((x name-p))
   :parents (name)
   :returns (xx name-p)
   :hooks nil
   (mbe :logic (if (name-p x) x '(:anonymous))
        :exec x)
   ///
   (defthm name-fix-when-name-p
     (implies (name-p x)
              (equal (name-fix x) x))))
 })

 <p>We now invoke the resulting executable, @('./sv-top').</p>

 @({
 ; Start ./sv-top, then:
 (set-fast-cert t state)
 (certify-book "name" ? t :ttags :all)
 })

 <p>In this little example, the certification time has been cut in half with
 fast-cert mode active.  In many cases the reduction may be less than that, but
 in large industrial examples the reduction might be much, much greater &mdash;
 -- especially when the book contains time-consuming events, in particular
 @('include-book') events.</p>")
other
(defxdoc fast-cert-anomalies
  :parents (fast-cert)
  :short "Potentially surprising consequences of using @(see fast-cert) mode"
  :long "<p>See @(see fast-cert) for relevant background.  This topic discusses
 some surprises one may encounter when using fast-cert mode.</p>

 <p>When fast-cert mode was developed in February 2023, a call of
 &ldquo;@('make')&rdquo; was made with &ldquo;@('ACL2_FAST_CERT=t')&rdquo; and
 target &ldquo;@('regression-everything')&rdquo;, to certify the @(see
 community-books) with fast-cert mode active.  There were only two
 failures (out of thousands of books), both of which are discussed below along
 with their fixes.  There is no plan to continue to test certification of the
 community books with fast-cert mode enabled, but we expect future failures to
 continue to be rare.</p>

 <h3>Example 1</h3>

 <p>Community book @('system/tests/early-load-of-compiled/ttag.lisp') has
 certified regardless of whether or not fast-cert mode is used.  However, when
 it was certified with fast-cert mode active, a later attempt to include the
 book failed.  That failure was due to the way ACL2 handles raw-Lisp
 redefinition (using a trust tag), as explained in a comment in the book.  To
 avoid this problem, the form @('(set-fast-cert nil state)') is in file
 @('ttag.acl2') in the same directory.  Key events in the book are as follows,
 in this order; the first forces a @(see local-incompatibility) check, and you
 can see comments in @('ttag.lisp') for why that is crucial.</p>

 @({
 (local (defun loc (x) x))

 (defun ttag-f (x)
   (declare (xargs :guard t))
   x)

 ; An assertion is here of (equal (ttag-f 3) 3), to be evaluated during both
 ; certify-book and include-book, basically of the form:
 (make-event ...) ; asserts (equal (ttag-f 3) 3)

 (progn!
  (set-raw-mode t)
  (defun ttag-f (x) (cons x x)))
 })

 <h3>Example 2</h3>

 <p>The second example is rather subtle.  Our starting point is the following,
 from community book
 @('rtl/rel9/support/lib2.delta1/add-new-proofs.lisp').</p>

 @({
 ; Matt K. addition: The following lemma, natp-lamz, is not normally necessary.
 ; But with fast-cert mode active, we need it for the proof of lam1_alt-is-lam1.
 ; See :DOC fast-cert-anomalies if you want an explanation.
 (local
  (defthm natp-lamz
    (natp (lamz a b e))
    :rule-classes :type-prescription))
 })

 <p>To see why this lemma is needed when certifying in fast-cert mode, let us
 start by re-creating the environment where the definition of @('lamz') has
 been introduced.  We assume here that the sub-books that are included were
 certified with fast-cert mode active.</p>

 @({
 (set-fast-cert t state) ; so that sub-books are included as certified
 (ld "rtl/rel9/support/lib2.delta1/add-new-proofs.lisp"
     :dir :system
     ;; to speed things up:
     :ld-skip-proofsp t)
 })

 <p>We see that the built-in @(see type-prescription) rule for @('lamz') says
 only that @('lamz') returns a rational number, not necessarily a non-negative
 integer.</p>

 @({
 ACL2 !>:pr lamz

 Rune:         (:TYPE-PRESCRIPTION LAMZ)
 Enabled:      T
 Hyps:         T
 Term:         (LAMZ A B E)
 Backchain-limit-lst: NIL
 Basic-ts:     *TS-RATIONAL*
 Vars:         NIL
 Corollary:    (RATIONALP (LAMZ A B E))

 ...
 })

 <p>If we do the same experiment when sub-books were certified with fast-cert
 mode disabled, the @(':')@(tsee pr) output will instead show a built-in @(see
 type-prescription) rule for @('lamz') saying that @('lamz') returns a
 non-negative integer.  This discrepancy in that built-in rule explains why the
 additional lemma above, @('natp-lamz'), was necessary when certifying the
 @(see community-books) with fast-cert mode active.</p>

 <p>So now let us investigate why certifying books with fast-cert mode active
 weakens the built-in type-prescription rule for @('lamz').  After running the
 @('set-fast-cert') and @(tsee ld) commands displayed above, we see where
 @('lamz') is defined.</p>

 @({
 ACL2 !>:pe lamz
    d       2  (LOCAL (INCLUDE-BOOK "../lib2/top"))
               
               [Included books, outermost to innermost:
                "/Users/kaufmann/acl2/acl2/books/rtl/rel9/support/lib2/top.lisp"
                "/Users/kaufmann/acl2/acl2/books/rtl/rel9/support/lib2/add.lisp"
               ]
               
 >L             (DEFUN LAMZ (A B E)
                       (LNOT (LIOR A (LNOT B (1+ E)) (1+ E))
                             (1+ E)))
 ACL2 !>
 })

 <p>But we need to work harder to find the real source of the definition of
 @('lamz').  In @('rtl/rel9/support/lib2/add.lisp') we see that the definition
 of @('lamz') is preceded by @('(set-enforce-redundancy t)') as well as
 @('(local (include-book "base"))').  When we invoke @(':ubt 1') and then
 @('(include-book "base")'), we can evaluate @(':pe lamz') to see that
 @('lamz') is defined in @('rtl/rel9/support/lib1/add.lisp'), which contains
 @('(set-enforce-redundancy t)') and the local event, @('(local (include-book
 "../support/top"))').  So we include <i>that</i> book after invoking @(':ubt
 1'), then (again) invoke @(':pe lamz'), and finally find the true source of
 the definition of @('lamz'): @('rtl/rel9/support/support/lextra.lisp').</p>

 <p>So now consider what happens when we start ACL2 and evaluate the following
 commands.  For now, assume that we have used ACL2 fast-cert mode disabled to
 certify all books being included.  We use @(':ld-skip-proofsp 'include-book')
 to simulate what happens when including the book.</p>

 @({
 ; with fast-cert mode disabled
 (ld "rtl/rel9/support/support/lextra.lisp"
     :dir :system
     :ld-skip-proofsp 'include-book)
 :ubt lamz
 (defun lamz (a b e)
   (lnot (lior a (lnot b (1+ e)) (1+ e)) (1+ e)))
 })

 <p>Then @(':pr lamz') shows a @(':type-prescription') rule for @('lamz') that
 this function returns a non-negative integer.  That is explained in part by
 the following output, which mentions a rule stating that @('lnot') returns a
 non-negative integer, which was used to compute the built-in type for
 @('lamz') that it returns a non-negative integer.</p>

 @({
 We used the :type-prescription rule LNOT-NONNEGATIVE-INTEGER-TYPE.
 })

 <p>Now repeat the same experiment but where we assume that fast-cert mode has
 been active for all book certification and we start with @('(set-fast-cert t
 state)').  This time there is no such output about
 @('LNOT-NONNEGATIVE-INTEGER-TYPE').  Aha!  The culprit is the following form
 near the top of @('"rtl/rel9/support/support/lextra.lisp"').</p>

 @({
 (local (in-theory (current-theory 'lextra0-start)))
 })

 <p>That form disables the @(':type-prescription') rule
 @('LNOT-NONNEGATIVE-INTEGER-TYPE'), which is necessary for computing a
 non-negative integer (i.e., @('natp')) type for the built-in
 @(':type-prescription') rule for @('lamz').  By contrast, without fast-cert
 mode active, the world is rolled back past local events for the
 local-incompatibility check, and then when events in the book are processed
 during the @('include-book') phase of certification, the rule
 @('LNOT-NONNEGATIVE-INTEGER-TYPE') is available for computing the built-in
 type-prescription for @('lamz'), which is stored in the book's @(see
 certificate).  But with fast-cert mode active, the world is not rolled back,
 so the built-in type-prescription for lamz remains as originally computed,
 where the rule @('LNOT-NONNEGATIVE-INTEGER-TYPE') is disabled.</p>

 <p>Indeed, if you read the certificate file for the @('lextra.lisp') book
 above, you'll see that the @(':TYPE-PRESCRIPTION') entry for @('lamz')
 indicates a rational type when books are certified with fast-cert mode active
 but a non-negative integer type when certified with fast-cert mode disabled.
 You can read that certificate file as follows.</p>

 @({
 (read-file (concatenate 'string
                         (system-books-dir state)
                         "rtl/rel9/support/support/lextra.cert")
            state)
 })")
other
(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>")
other
(defxdoc fifth
  :parents (nth acl2-built-ins)
  :short "Fifth member of the list"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(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$)")
other
(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>")
other
(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>

 <p>This utility provides a reasonable way to determine whether a file exists,
 like Common Lisp's @('probe-file'), according to whether @('D') is
 non-@('nil') in when @('(mv D state)') is returned.</p>

 @(def file-write-date$)")
other
(defxdoc finalize-event-user
  :parents (output-controls)
  :short "User-supplied code to complete @(see events), e.g., with extra @(see
 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 @(see 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))
            (newline *standard-co* state)))
          (t state)))

  (defattach-system finalize-event-user finalize-event-user-test)
 })

 <p>After admission of the two events above, an event @(see 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 (ctx body 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-system (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>")
other
(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>")
other
(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>")
other
(defxdoc first
  :parents (nth acl2-built-ins)
  :short "First member of the list"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(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.  See @(see the-number) for a
 variant of @('fix') whose guard specifies a numeric argument.</p>

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

 @(def fix)")
other
(defxdoc fix-true-list
  :parents (lists acl2-built-ins)
  :short "Coerce to a true list"
  :long "<p>@('Fix-true-list') is a macro that expands to a call of @(tsee
  true-list-fix) with the same argument.</p>

 @(def fix-true-list)")
other
(defxdoc flet
  :parents (basics acl2-built-ins)
  :short "Local binding of function symbols"
  :long "<p>See @(see macrolet) for an analogous utility for defining macros
 locally.</p>

 @({
 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), but
 see @(see declare) for the declarations permitted directly under the
 @('defi').  On the other hand, regarding the @('declare-formi') (if any are
 supplied): 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 innermost @('flet') or @(tsee macrolet) binding of a symbol, @('f'),
 above a call of @('f'), is the one that provides the definition of @('f') for
 that call.  Note that neither @('flet') nor @('macrolet') provide recursion:
 that is, the definition of @('f') in an @('flet') or @('macrolet') binding of
 @('f') is ignored in the body of that binding.  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.  Such @('type') declarations affect evaluation and @(see
 guard)-checking in a way that is completely analogous to such declarations
 that occur between the formal parameters and the body in a @(tsee defun)
 form.</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>

 <li>When an expression @('(flet (... defi ...) ...)') occurs in the body of a
 @('DO') @(tsee loop$) expression, nevertheless constructs such as @('PROGN')
 and @('SETQ') that ACL2 permits in @('DO') @('loop$') bodies are not permitted
 in @('defi') (unless they occur within the scope of a @('DO') @('loop$')
 expression in that body).  (This restriction is only for ACL2; for example, it
 may be reasonable to call @('RETURN') in such situations but ACL2 does not
 allow that.)</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>")
other
(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, that is, the quotient of the
 division, while the remainder is returned by @(tsee mod).</p>

 @(def floor)")
other
(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)")
other
(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>")
other
(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>")
other
(defxdoc fms!
  :parents (io acl2-built-ins)
  :short "@('(fms! str alist co-channel state evisc) => state')"
  :long "<p>This function is nearly the same as @(tsee fms), but @('fms!')
 avoids inserting backslash (\) characters when forced to print past the right
 margin.  Use @('fms!') if you want to be able to read the forms back in.</p>")
other
(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).  A convenient macro, @('fmx'), is
 described below; also see @(see cw) and see @(see fmx-cw).</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 and generally avoided in this manual.  These are
 respectively the same as @('~x'), @('~y'), @('~X'), and @('~Y'), except that
 their arguments may be expected to be terms, preferably
 untranslated (user-level) terms, since at one time there was the possibility
 that they could be printed using infix notation in certain environments.
 Infix printing is no longer supported, however.</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.  A right margin of 40 is used for
 pretty printing with @('~y'), @('~Y'), @('~q'), and @('~Q') and can be changed
 to a positive integer @('N') with @('(set-ppr-flat-right-margin N
 state)').</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, @('fmx').  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; for similar utilities that do not
 take or return @(see state), see @(see cw) and @(see fmx-cw).  The variables
 used are @('#\0') through @('#\9').  The macro constructs an appropriate
 alist, @('a'), and then evaluates @('(fmt` str a 0 *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>

 @({
  (fmt1 "~%Here is v0, ~x0, and here is v1, ~x1."
        (list (cons #\0 (cons 'value 0))
              (cons #\1 (cons 'value 1)))
        0
        *standard-co*
        state
        nil)
 })

 <p>which returns @('(mv 53 state)') after printing, on a separate 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>")
other
(defxdoc fmt!
  :parents (io acl2-built-ins)
  :short "@('(fmt! str alist co-channel state evisc) => state')"
  :long "<p>This function is nearly the same as @(tsee fmt), but @('fmt!')
 avoids inserting backslash (\) characters when forced to print past the right
 margin.  Use @('fmt!') if you want to be able to read the forms back in.</p>")
other
(defxdoc fmt-to-comment-window
  :parents (cw io acl2-built-ins)
  :short "Print to the comment window"
  :long "
 @({
  General Form:
  (fmt-to-comment-window fmt-string alist col evisc-tuple print-base-radix)
 })

 <p>where these arguments are as described for @(tsee fmt1) (see @(see fmt))
 except that the last argument is as described for @(tsee
 cw-print-base-radix).</p>

 <p>See @(see cw) for important background.  Calls of the macro @('cw') expand
 to calls of the function @('fmt-to-comment-window') whose final three
 arguments are @('0'), @('nil'), and @('nil').  For variants of
 @('fmt-to-comment-window') that provide readable output (suffix @('"!"'))
 and are never inhibited (suffix @('"+"')), see @(see
 fmt-to-comment-window!), @(see fmt-to-comment-window+), and @(see
 fmt-to-comment-window!+).</p>

 <p>Function @('fmt-to-comment-window') is similar 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, and moreover, an additional argument
 specifies the print-base and optionally the print-radix.  That additional
 argument is treated the same as the first argument of
 @('cw-print-base-radix'); see @(see cw-print-base-radix).  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!), a macro that expands to a call of
 @('fmt-to-comment-window!').  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>")
other
(defxdoc fmt-to-comment-window!
  :parents (cw io acl2-built-ins)
  :short "Print readably to the comment window"
  :long "<p>See @(see cw) for important background.</p>

 <p>This is nearly the same as @(tsee fmt-to-comment-window), but
 @('fmt-to-comment-window!') avoids inserting backslash (\) characters when
 forced to print past the right margin.  Use @('fmt-to-comment-window!') if you
 want to be able to read the forms back in.</p>")
other
(defxdoc fmt-to-comment-window+
  :parents (cw io acl2-built-ins)
  :short "Print uninhibited to the comment window"
  :long "<p>See @(see cw) for important background.</p>

 <p>This is nearly the same as @(tsee fmt-to-comment-window), but
 @('fmt-to-comment-window+') always produces output, even when the @('COMMENT')
 output type is inhibited (see @(see set-inhibit-output-lst)).</p>")
other
(defxdoc fmt-to-comment-window!+
  :parents (cw io acl2-built-ins)
  :short "Print readably and uninhibited to the comment window"
  :long "<p>See @(see cw) for important background.</p>

 <p>This is nearly the same as @(tsee fmt-to-comment-window), but
 @('fmt-to-comment-window!+') always produces readable output (like @(tsee
 fmt-to-comment-window!)), even when the @('COMMENT') output type is
 inhibited (like @(tsee fmt-to-comment-window+)).</p>")
other
(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>")
other
(defxdoc fmt1!
  :parents (io acl2-built-ins)
  :short "@('(fmt1! str alist col channel state evisc) => (mv col state)')"
  :long "<p>This function is nearly the same as @(tsee fmt1), but @('fmt1!')
 avoids inserting backslash (\) characters when forced to print past the right
 margin.  Use @('fmt1!') if you want to be able to read the forms back
 in.</p>")
other
(defxdoc fmx
  :parents (io acl2-built-ins)
  :short "@('(fmx str &rest args) => state')"
  :long "<p>See @(see fmt) for further explanation, including documentation of
 the tilde-directives.</p>")
other
(defxdoc fmx-cw
  :parents (io acl2-built-ins)
  :short "@('(fmx-cw str &rest args) => state')"
  :long "<p>@('Fmx-cw') is a variant of @('cw'): both take the same arguments
 and have the same behavior on well-formed input, and both return @('nil').
 See @(see cw) for documentation on how to use both utilities.  Unlike @('cw'),
 which has a @(see guard) of @('t'), @('fmx-cw') has a non-trivial guard that
 can catch errors in the use of tilde-directives.  Here is an example of
 such a guard violation, where the corresponding call of @('cw') would instead
 cause a hard error.</p>

 @({
 ACL2 !>(fmx-cw "Hello ~s0." '(world))


 ACL2 Error in TOP-LEVEL:  Guard violation for FMX-CW-FN:
 Illegal Fmt Syntax.  The tilde-s directive at position 6 of the string
 below is illegal because its variable evaluated to (WORLD), which is
 not a symbol, a string, or a number.

 "Hello ~s0."

 ACL2 !>
 })

 <p>Thus, call @('fmx-cw') instead of @('cw') in the body of @(':')@(tsee
 logic) mode definition when you want its @(see guard) verification to help
 ensure the absence of runtime errors from that call.  Note that if you call
 @('fmx-cw') in a definition, the guard proof may benefit from the lemma,
 @('fmx-cw-msg-1-opener'), found in @(see community-book)
 @('books/system/fmx-cw.lisp').</p>

 <p>The variant @('fmx!-cw') avoids the insertion of backslash () characters
 when forced to print past the right margin.  Thus, use @('fmx!-cw') instead of
 @('fmx-cw') if you want the output to be machine-readable.</p>")
other
(defxdoc fn-equal
  :parents (apply$ defwarrant)
  :short "Equivalence relation on tame functions"
  :long "<p>@('Fn-equal') is an equivalence relation on tame functions.  It
  holds between @('fn1') and @('fn2') iff both are tame functions and
  @('(apply$ fn1 args)') is @('(apply$ fn2 args)'), for all @('args').  A
  @('defun-sk') event is used to express the universally quantified condition.
  @(tsee defwarrant) proves that @('fn-equal') is a congruence relation for
  every argument position of ilk @(':FN').</p>

  <p>Ideally one can substitute one functional object for an equivalent one in
  functional positions.  For example, @('fn-equal') holds between
  <tt>'(LAMBDA (X) X)</tt> and <tt>'IDENTITY</tt>, so one would hold that
  <tt>(collect$ '(LAMBDA (X) X) lst)</tt> could be rewritten to <tt>(collect$
  'IDENTITY lst)</tt> since the first argument of @('collect$') (as defined in
  the @(see introduction-to-apply$)) has ilk @(':FN').  Unfortunately, because
  these are quoted constants, ACL2's rewriter will not rewrite one to the
  other!</p>

  <p>We regard @('fn-equal') as a reminder to us &mdash; or a challenge to
  users!  &mdash; to find a way to handle functional equivalence in the
  rewriter.</p>")
other
(defxdoc for-loop$
  :parents (loop$)
  :short "Iteration with @(tsee loop$) over an interval of integers or a list"
  :long "<p>This topic assumes that you have read the introduction to
  @('loop$') expressions in ACL2; see @(see loop$).  Here we give more complete
  documentation on @('FOR') @('loop$') expressions, beginning with informal
  discussion and then continuing with detailed syntax (General Form) and
  semantics.  For a discussion of proofs about @('loop$')s, see @(see
  stating-and-proving-lemmas-about-loop$s).</p>

  <p>Examples of @(tsee loop$) expressions, including @('FOR') @('loop$')s, may
  be found in @(see community-book) @('projects/apply/loop-tests.lisp').</p>

  <p>The only allowed iteration clauses are @('IN'), where the variable ranges
  over the elements of the given true list; @('ON'), where the variable ranges
  over the tails of the given true-list; and @('FROM/TO/BY'), where the
  variable ranges over the integers between two bounds, stepping by a positive
  integer increment (or by 1 if no @('BY') clause is provided).</p>

  <p>You may have as many iteration clauses as you wish, connected with
  @('AS').  Each must introduce a unique iteration variable and that variable
  may be optionally followed by an @('OF-TYPE') @(see type-spec) specification.
  @('OF-TYPE') is a Common Lisp feature that allows the compiler to optimize
  operations on the variable in question.  Here is an example.</p>

  @({
  (loop$ for v of-type (and integer (not (satisfies zerop)))
               from 1 to 100
         sum (/ 1 v))
  })

  <p>Here is that same example with a more concise type specification.</p>

  @({
  (loop$ for v of-type (integer 1 *)
               from 1 to 100
         sum (/ 1 v))
  })

  <p>After all of the iteration clauses, you may have a termination test,
  signaled by @('UNTIL'), and/or a conditional test, signaled by @('WHEN').  If
  both are provided, the @('UNTIL') test must come first.  Iteration stops when
  the @('UNTIL') test is satisfied.  The conditional test determines whether
  the loop body is executed for the current value of the iteration
  variables.</p>

  <p>Between the @('UNTIL') symbol and the expression to be tested, and between
  the @('WHEN') symbol and its expression, you may include a @(':GUARD')
  clause.  This is useful if @(see guard) verification requires an invariant
  relating multiple iteration variables.  An example of a guarded @('UNTIL')
  clause is</p>

  @({
  (loop$ for u in lst1 as v in lst2
         until :guard (invariantp u v) (test u v)
         collect (body u v))
  })

  <p>ACL2 supports only five operators in @('FOR') @('loop$')s: @('SUM'),
  @('COLLECT'), @('ALWAYS'), @('THEREIS') and @('APPEND').  We anticipate
  adding other Common Lisp operators eventually.</p>

  <p>The special symbols noted above, sometimes called ``@('FOR') @('loop$')
  keywords'' or just ``@('loop$') keywords'' may be in any package.  These are
  @('FOR'), @('IN'), @('ON'), @('FROM'), @('TO'), @('BY'), @('OF-TYPE'),
  @('WHEN'), @('UNTIL'), @('SUM'), @('COLLECT'), @('ALWAYS'), @('THEREIS'), and
  @('APPEND').</p>

  <p>Between the operator, e.g., @('SUM') or @('COLLECT'), and the
  @('loop$') body you may include a @(':GUARD') clause as in</p>

  @({
  (loop$ for u in lst1 as v in lst2
         collect :guard (invariantp u v) (body u v))
  })

  <p>This is sometimes necessary in the verification of the @(see guard)s for
  the @('loop$') body because Common Lisp's @('OF-TYPE') clauses do not permit
  you to relate one variable to another.</p>

  <p>See @(see lp-section-6) of the @('Loop$') Primer for some exercises in
  writing @('FOR') @('Loop$')s (with answers in a Community Book).  But
  remember to come back here when you get to the end of that section.</p>

  <h3>General Form</h3>

  <p>The syntax of Common Lisp @('loop') expressions is extremely complicated.
  Rather than try to write the abstract syntax of ACL2's @('loop$') expressions
  in the same formal style, we take a different approach, which is workable
  because @('loop$') allows fewer options.</p>

  <p>First we introduce the syntax of a ``target clause,'' a ``type-spec,'' and
  the ``operators.''  Then we describe the most elaborate form of a @('loop$')
  expression in terms of these elements and ordinary ACL2 terms.  Every legal
  @('loop$') expression can be produced by omitting certain optional elements
  from the most elaborate @('loop$') form.  So we conclude the syntactic
  description of @('loop$') by listing the elements that can be omitted.</p>

  <p>A <i>target clause</i> has one of four forms</p>

  <ul>

  <li>@('IN') <i>list-expr</i></li>

  <li>@('ON') <i>expr</i></li>

  <li>@('FROM') <i>lo-expr</i> @('TO') <i>hi-expr</i></li>

  <li>@('FROM') <i>lo-expr</i> @('TO') <i>hi-expr</i> @('BY')
  <i>step-expr</i></li>

  </ul>

  <p>where <i>list-expr</i> is a term (which is expected to evaluate to a true
  list), <i>expr</i> is a term, <i>lo-expr</i> and <i>hi-expr</i> are
  terms (which are expected to evaluate to integers), and <i>step-expr</i> is a
  term (which is expected to evaluate to a positive integer).</p>

  <p>The legal <i>type-specs</i> are listed in @(tsee type-spec).</p>

  <p>The legal <i>operators</i> are @('SUM'), @('COLLECT'), @('ALWAYS'),
  @('THEREIS'), and @('APPEND').</p>

  <p>The most elaborate @('loop$') expression is of the form</p>

  <p>&nbsp; &nbsp; &nbsp; &nbsp; @('(LOOP$ FOR ')<i>v1</i>@(' OF-TYPE ')<i>spec1
  target1</i><br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
  &nbsp; &nbsp; &nbsp; &nbsp; @('AS ') &nbsp; <i>v2</i>@(' OF-TYPE ')<i>spec2
  target2</i><br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
  &nbsp; &nbsp; &nbsp; &nbsp; ...<br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
  &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @('AS ') &nbsp; <i>vn</i>@('
  OF-TYPE ')<i>specn targetn</i><br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
  &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @('UNTIL :GUARD ')<i>guard1
  until-expr</i><br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
  &nbsp; &nbsp; &nbsp; &nbsp; @('WHEN ') &nbsp; @(':GUARD ')<i>guard2
  when-expr</i><br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
  &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; Note the @('ALWAYS')/@('THEREIS') Exceptions
  below!<br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
  &nbsp; &nbsp; &nbsp; <i>op</i>@(' :GUARD ')<i>guard3
  body-expr</i>@(')')<br/></p>

  <p>where each <i>vi</i> &nbsp; is a legal variable symbol and they are all
  distinct, each <i>type-speci</i> &nbsp; is a @(tsee type-spec), each
  <i>targeti</i> &nbsp; is a target clause, each <i>guardi</i>,
  <i>until-expr</i>, and <i>when-expr</i> &nbsp; is a term, <i>op</i> &nbsp; is
  an operator, and <i>body-expr</i> &nbsp; is a term.  Furthermore,
  <i>until-expr</i>, <i>when-expr</i>, and <i>body-expr</i> &nbsp; must be
  @(see tame)!</p>

  <p><i>The @('ALWAYS')/@('THEREIS') Exception:</i> Common Lisp prohibits loops
  with both a @('WHEN') clause and either an @('ALWAYS') or a @('THEREIS')
  operator.  For example, if you are tempted to use @('WHEN') <i>p</i> with
  @('ALWAYS') <i>q</i> you can instead write @('ALWAYS') @('(implies ')<i>p
  q</i>@(')') or, if you want to evaluate @('q') only when @('p') is true, you
  can write @('ALWAYS') @('(if ')<i>p q</i> @('t)').</p>

  <p>The following elements may be omitted.</p>

  <ul>
  <li>any line beginning with @('AS'), @('UNTIL') or @('WHEN'),</li>

  <li>any @('OF-TYPE') <i>speci</i>, and</li>

  <li>any @(':GUARD') <i>guardi</i>.</li>

  </ul>

  <p>As noted above, the @('FOR') @('loop$') keywords (as used above) may be in
  any package.  These are @('FOR'), @('IN'), @('ON'), @('FROM'), @('TO'),
  @('BY'), @('OF-TYPE'), @('WHEN'), @('UNTIL'), @('SUM'), @('COLLECT'),
  @('ALWAYS'), @('THEREIS'), and @('APPEND').</p>

  <p>We give names to certain classes of the syntactic entities above.  The
  <i>v1</i>, ..., <i>vn</i> are called the <i>iteration variables</i>.  The
  <i>spec1</i>, ..., <i>specn</i> are called <i>type specs</i>, each
  corresponds to a certain iteration variable, and each gives rise to a <i>type
  term</i> about its variable in the sense that ``@('X OF-TYPE (SATISFIES
  NATP)')'' gives rise to the type term @('(NATP X)') and ``@('I OF-TYPE
  INTEGER')'' gives rise to the type term @('(INTEGERP I)').  The terms
  involved in the target expressions, e.g., the <i>list-expr</i> and
  <i>expr</i> in ``@('IN') <i>list-expr</i>'' and ``@('ON') <i>expr</i>'' and
  the <i>lo-expr</i>, <i>hi-expr</i> and optional <i>step-expr</i> in the
  ``@('FROM') <i>lo-expr</i> @('TO') <i>hi-expr</i> @('BY') <i>step-expr</i>''
  targets are called <i>target terms</i>.  Finally, the <i>until-expr</i>,
  <i>when-expr</i>, and <i>body-expr</i> are called <i>iterative forms</i>.</p>

  <p>We distinguish the target terms from the iterative forms because they are
  handled very differently at evaluation time.  When a @('loop$') is evaluated,
  the target terms are evaluated just once.  But the iterative forms are
  evaluated multiple times as the iteration variables range over the values of
  the targets.</p>

  <p>A @('FOR') @('loop$') expression with just one iteration variable and in
  which the iterative forms mention no free variable other than the iteration
  variable is called a <i>simple @('loop$')</i> (or, sometimes, a <i>simple
  loop</i>).  An example of a simple loop is</p>

  @({
  (loop$ for x in lst when (evenp x) collect (+ 1 (sq x)))
  })

  <p>A @('FOR') @('loop$') expression is called a <i>fancy @('loop$')</i> if it
  is not simple.  Both of the following @('loop$')s are fancy.</p>

  @({
  (loop$ for x in xlst as y on ylst collect (expr x y))

  (loop$ for x in xlst collect (expr x z))
  })

  <p>The first is fancy because it has two iteration variables.  The second is
  fancy because the body freely uses the variable @('z') which is not the
  iteration variable.  The free variables cannot be @(see stobj)s or @(see
  df)s, since the translation of the @('loop$') will put them into a list; see
  discussion of the semantics, below.  In such cases you may wish to use
  @('DO') @('loop$') expressions (see @(see do-loop$)) instead.</p>

  <h3>Semantics</h3>

  <p>@('FOR') @('loop$') expressions are translated into calls of @(see
  scion)s, with the @('UNTIL') and @('WHEN') clauses translated into
  preprocessors of the targets.  But which scions are used depend on whether
  the loop is simple or fancy.  Recall that a fancy loop is one that has either
  or both of the following characteristics: (a) there is one or more @('as')
  clauses, and/or (b) one of the iterative forms (the @('UNTIL'), @('WHEN') or
  loop body expression) refers to variables other than an iteration variable.
  If the @('loop$') expression is simple, the simple scions are used; otherwise
  the fancy scions are used.</p>

  @({
   loop$               simple          fancy
   keyword             scion           scion
   ______________________________________________
   SUM                 sum$            sum$+
   COLLECT             collect$        collect$+
   ALWAYS              always$         always$+
   THEREIS             thereis$        thereis$+
   APPEND              append$         append$+
   UNTIL               until$          until$+
   WHEN                when$           when$+
   })

  <p>We deal with simple @('loop$')s first.</p>

  <h4>Semantics of Simple Loop$s</h4>

  <p>For example, the simple @('loop$')</p>
  @({
  (loop$ for x in lst collect (+ 1 (sq x)))
  })
  <p>translates to (a term equivalent to)</p>

  @({
  (collect$ (lambda$ (x)
                     (declare (ignorable x))
                     (+ 1 (sq x)))
            lst).
  })

  <p><b>Note:</b> The actual translation is tagged with various markers that
  play a role in evaluation but which are logically irrelevant and which are
  removed during proof.  In this discussion we will not display the marked-up
  translations but logically equivalent terms instead.  You can see the actual
  translations for yourself with @(tsee trans).</p>

  <p>In the translation the target term, @('lst'), appears as an ordinary
  subterm of the translation.  But the iterative form, @('(+ 1 (sq x))'),
  becomes the body of a @(tsee lambda$) expression, which means its translation
  becomes a component of a quoted @('LAMBDA') object.  When the @('collect$')
  is evaluated, the target term is evaluated once but the iterative form is
  evaluated once for each element of the value of the target.</p>

  <p>@('UNTIL') and @('WHEN') clauses are handled by preprocessing the target.
  E.g.,</p>

  @({
  (loop$ for x in lst
         until (> x 100)
         when (evenp x)
         collect (+ 1 (sq x)))
  })

  <p>becomes</p>

  @({
  (collect$ (lambda$ (x)
                     (declare (ignorable x))
                     (+ 1 (sq x)))
            (when$ (lambda$ (x)
                            (declare (ignorable x))
                            (evenp x))
                   (until$ (lambda$ (x)
                                    (declare (ignorable x))
                                    (> x 100))
                           lst)))
  })

  <p>So from a logical perspective, the presence of an @('UNTIL') and/or
  @('WHEN') clause in a @('collect') iteration over @('lst') ``copies'' the
  target value.  The @('until$') copies @('lst') until encountering the first
  element on which its functional argument is true.  The @('when$') then copies
  that (shortened?) target, keeping only the elements that satisfy its
  functional argument.  Finally, the @('collect$') then applies its functional
  argument and collects all the values.</p>

  <p>@('ON') and @('FROM/TO/BY') targets are handled by listing all the
  elements in the given target.  For example,</p>

  @({
  (loop$ for x on lst collect (expr x))
  })

  <p>which maps @('x') over successive non-empty tails of @('lst') and collects
  the value of @('expr') has the logical meaning</p>

  @({
  (collect$ (lambda$ (x) (expr x))
            (tails lst))
  })

  <p>where, for example, @('(tails '(1 2 3))') is @('((1 2 3) (2 3) (3))').</p>

  <p>Spiritually similarly,</p>
  @({
  (loop$ for i from 1 to max by step collect (expr x))
  })

  <p>logically becomes</p>

  @({
  (collect$ (lambda$ (x) (expr x))
            (from-to-by 1 max step))
  })

  <p>where, for example, @('(from-to-by 1 10 2)') is @('(1 3 5 7 9)').</p>

  <p>Similar translations are done for the other operators, e.g., @('SUM') and
  @('ALWAYS').  The advantage of this translation style is that it allows
  compositional reasoning.  We discuss this further below.</p>

  <p>The following example illustrates basic @(see guard) proof obligations, in
  particular showing that @('WHEN') clauses do not help with verifying guards
  for the @('loop$') bodies.  (Similarly, @('UNTIL') clauses do not help
  either.)  The basic problem is that ACL2 requires that @(tsee lambda) objects
  be guard verifiable in isolation, not confined to the context in which a
  particular @('lambda') object appears.  Consider the following.</p>

  @({
  (include-book "projects/apply/top" :dir :system)
  (defun$ sq (n)
    (declare (xargs :guard (natp n)))
    (* n n))
  (defun foo (lst)
    (declare (xargs :guard (nat-listp lst)))
    (loop$ for x of-type (satisfies nat-listp) on lst
           when (consp x)
           sum (sq (car x))))
  })

  <p>Guard verification fails for @('foo').  The summary says that a goal of
  @('NIL') was generated.  Using @(':')@(tsee pso) we can see that the @('NIL')
  goal came from:</p>

  @({
  Subgoal 1.2
  (IMPLIES (NAT-LISTP LOOP$-IVAR)
           (INTEGERP (CAR LOOP$-IVAR))).
  })

  <p>Let's see what is going on by looking at the following simplified
  translation of the @('loop$') expression.</p>

  @({
  (sum$ '(lambda (loop$-ivar)
           (declare (type (satisfies nat-listp) loop$-ivar))
           (sq (car loop$-ivar)))
        (when$ '(lambda ...) (tails lst)))
  })

  <p>Notice that the @('lambda') object supplied to @('sum$') cannot be guard
  verified in isolation: @('nil') satisfies the @(':guard') and @('(car nil)')
  violates the guard of @('sq').  The following modification, which adds a
  @(':guard') directive after the @('SUM') op keyword, solves the problem.</p>

  @({
  (defun foo (lst)
    (declare (xargs :guard (nat-listp lst)))
    (loop$ for x of-type (satisfies nat-listp) on lst
           when (consp x)
           sum :guard (consp x)  ; note new :guard
           (sq (car x))))
  })

  <p>This new @(':guard') may feel redundant, coming as it does after the
  @('when (consp x)') clause.  But it is necessary given the compositional
  semantics.</p>

  <p>A simplified translation of the @('defun') above shows that the
  application @('(sq (car x))') is protected by a suitable guard in the
  @('lambda') object.</p>

  @({
  (sum$ '(lambda (loop$-ivar)
           (declare (type (satisfies nat-listp) loop$-ivar)
                    (xargs :guard (consp loop$-ivar)))
           (sq (car loop$-ivar)))
        (when$ '(lambda ...) (tails lst)))
  })

  <p>Naively we might have expected that the guard proof obligation for the
  @('loop$') body @('(sq (car x))') could assume the @('WHEN') clause, but that
  expectation would be wrong because of the compositional semantics we use and
  the fact that @(tsee lambda) objects must be guard-verifiable on their own.
  The reason for the latter requirement is that our implementation caches
  guard-verified @('lambda') objects for evaluation in raw Lisp, which may take
  place in other contexts different from that in which the @('lambda') first
  appeared.  See @(see print-cl-cache).</p>

  <h4>Semantics of Fancy Loop$s</h4>

  <p>An example of a fancy @('loop$') is</p>

  @({
  (loop$ for x in xlst as y in ylst collect (expr x y z))
  })

  <p>This loop exhibits both characteristics (a) and (b): it has an @('AS')
  clause and the variable @('z') appears in the loop body.  Either
  characteristic is sufficient to classify the loop as fancy.  So fancy scions
  are used.  Here is its semantic counterpart, i.e., its simplified
  translation.</p>

  @({
  (collect$+
   (lambda$ (loop$-gvars loop$-ivars)
            (declare (xargs :guard (and (true-listp loop$-gvars)
                                        (equal (len loop$-gvars) 1)
                                        (true-listp loop$-ivars)
                                        (equal (len loop$-ivars) 2))))
            (let ((z (car loop$-gvars))
                  (x (car loop$-ivars))
                  (y (car (cdr loop$-ivars))))
              (declare (ignorable x y))
              (expr x y z)))
   (list z)
   (loop$-as (list xlst ylst)))
   })

  <p>Before we show the definition of @('collect$+'), note that the arguments
  above to @('collect$+') are (i) a @('lambda$') expression that handles the
  evaluation of the iterative form, in this case @('(expr x y z)'), where
  @('x') and @('y') are iteration variables and @('z') is a ``global'' variable
  not among the iteration variables; (ii) the list of values of the ``global''
  variables, in this case the list containing @('z'); and (iii) a target list
  constructed by @('loop$-as') from the various targets provided in the
  @('loop$'), in this case @('xlst') and @('ylst'), supplying values for
  iteration variables @('x') and @('y') respectively.  For example,
  @('(loop$-as (list '(a b c d e) '(1 2 3)))') is @('((a 1) (b 2) (c 3))').
  These tuples contain successive corresponding values of @('x') and
  @('y').</p>

  <p>The definition of @('collect$+') is essentially</p>
  @({
  (defun collect$+ (fn loop$-gvars lst)
    (if (endp lst)
        nil
        (cons (apply$ fn (list loop$-gvars (car lst)))
              (collect$+ fn loop$-gvars (cdr lst)))))
  })

  <p>We have omitted the guard and an @(tsee MBE) form that make it run more
  efficiently.  All the fancy @('loop$') scions are defined analogously.</p>

  <p>Inspection of the @('lambda$') expression above reveals that it takes a
  list of global variable values and a list of iteration variable values,
  unpacks them with a @('let') that binds the global variables, here just
  @('z'), to their values and binds the iteration variables, here @('x') and
  @('y'), to the corresponding pair of values from the target, and then
  evaluates the @('loop$') body, @('(expr x y z)').</p>

  <p>The names of the formals for the @('lambda$') expressions generated by
  fancy @('loop$') expressions are always @('loop$-gvars') and
  @('loop$-ivars'), for ``@('loop$') global variables'' and ``@('loop$')
  iteration variables.''</p>

  <p>@('UNTIL') and @('WHEN') clauses in a fancy @('loop$') are handled exactly
  as they are in simple @('loop$')s, except that the fancy scions are used
  since the target list is a list of tuples of iteration variable values and
  the @('UNTIL') and @('WHEN') forms may refer to global variables.</p>

  <p>See @(see lp-section-10) of the @('Loop$') Primer for a step-by-step
  discussion of the evaluation of the formal semantics of an example of a fancy
  @('Loop$').  But remember to come back here when you get to the end of that
  section.</p>

  <h4>Special Guard Conjectures for @('FOR') @('loop$')s</h4>

  <p>Since every @('loop$') expands to a call of a @('loop$') scion on a lambda
  object and a target, one would expect that @(see guard) verification would
  generate the guard conjectures for that scion and target.  Indeed, it does.
  In particular, the lambda object must have the correct number of
  formals (which is guaranteed by translation) and the target must satisfy
  @(tsee true-listp).</p>

  <p>But in addition to the expected guard conjectures, we generate some
  special ones for the terms produced by translating @('FOR') @('loop$')
  expressions.  We discuss the reasons in the next section, but here we just
  state what the special conjectures are.  We limit ourselves to a simple
  @('loop$').  Fancy @('loop$')s generalize in the obvious way.  The two
  classes of ``special guard conjectures'' for @('FOR') @('loop$') expressions
  are as follows.</p>

  <ul>

  <li>First, every element (or tail, in the case of @('ON') @('loop$')s))
  satisfies the type-spec, if any, and the @('loop$') body's @(':GUARD'), if
  any.</li>

  <li>Second, the @('loop$') body produces a value acceptable to the @('loop$')
  operator, e.g., the body of a @('SUM') @('loop$') produces a number and
  the body of an @('APPEND') @('loop$') produces a true list.</li>

  </ul>

  <p>See @(see lp-section-8) of the @('Loop$') Primer for some exercises in
  converting recursive functions to guard verified functions using @('FOR')
  @('loop$')s rather than recursion (with answers in a Community Book).  But
  remember to come back here when you get to the end of that section.</p>

  <h4>Discussion of Why LOOP$s Have Special Guards</h4>

  <p>All of the simple @('loop$') scions have the same guard, namely</p>

  @({
  (AND (APPLY$-GUARD FN '(NIL))
       (TRUE-LISTP LST)),
  })

  <p>and all the fancy @('loop$') scions have the same guard, namely</p>

  @({
  (AND (APPLY$-GUARD FN '(NIL NIL))
       (TRUE-LISTP LOOP$-GVARS)
       (TRUE-LIST-LISTP LST)).
  })

  <p>In addition to the normal guard conjectures that would be generated by
  calls of these scions, ACL2 generates some special guard conjectures because
  the normal guard conjectures are insufficient to guarantee the error-free
  execution of the corresponding Common Lisp @('loop') expressions.</p>

  <p>For example, the simplified translation of the body of</p>

  @({
  (defun foo (lst)
    (declare (xargs :guard (foo-guardp lst)))
    (loop$ for x of-type (satisfies spec) on lst sum (expr x)))
  })

  <p>is as follows.  (One might expect the second argument of the @('sum$')
  call to be @('(tails lst)'), and of course that is what it equals, logically;
  the change is to support guards, as discussed in the Technical Note
  below.)</p>

  @({
  (sum$ (lambda$ (loop$-ivar)
                 (declare (type (satisfies spec) loop$-ivar))
                 (expr loop$-ivar))
        (tails (prog2$ (let ((loop$-last-cdr (last-cdr lst)))
                         (declare (type (satisfies spec) loop$-last-cdr))
                         loop$-last-cdr)
                       lst)))
  })

  <p>Prior to the provision for special guards, the normal guard conjectures
  generated for @('foo') would be</p>

  @({
  (and (implies (foo-guardp lst)                                 ; [1]
                (apply$-guard
                 (lambda$ (loop$-ivar)
                   (expr loop$-ivar))
                 '(nil)))
       (implies (foo-guardp lst)                                 ; [2]
                (true-listp (tails lst)))
       (implies (spec loop$-ivar) (expr-guardp loop$-ivar)))     ; [3]
       (implies (foo-guardp lst)                                 ; [4]
                (let ((loop$-last-cdr (last-cdr lst)))
                     (spec loop$-last-cdr)))
  })

  <p>Conjectures [1] and [2] stem from the guard for @('sum$') and establish
  that the guard for @('foo') implies that @('sum$') is passed a function
  object of one argument and a true-list.  Conjecture [3] establishes that the
  guard on the @('lambda$') implies the guard of its body.  Conjecture [4] says
  that the final tail of @('lst') (which is @('nil') if @('lst') is a true
  list; see @(see last-cdr)) satisfies @('spec').  At first [4] may be
  surprising, but inspection of Common Lisp reveals that even though @('(expr
  x)') is never called on the final tail of @('lst'), implementations running
  with high safety settings check that the final tail satisfies @('spec').  If
  you see a runtime guard violation involving variable @('loop$-last-cdr'), you
  can reasonably assume that you are seeing case [4] above.  A guard proof
  failure involving a call of @(tsee last-cdr) may also be from [4].</p>

  <p>(Technical Note.  The production of [4] is accomplished as follows for an
  expression @('(loop for var of-type type-spec on lst ...)'): for the
  translation to a scion call, the target term, @('lst'), is replaced by the
  following expression (simplifying slightly).</p>

  @({
  (prog2$ (let ((loop$-last-cdr (last-cdr lst)))
            (declare (type type-spec loop$-last-cdr))
            loop$-last-cdr)
          lst)
  })

  <p>The @(tsee declare) form causes formula [4] above to be generated as a
  guard proof obligation.  End of Technical Note.)</p>

  <p>The guard proof obligation shown as [4] above, for an expression @('(loop$
  for ... on ...)'), has a variant for an expression @('(loop$ for n from i to
  j by k ...)'), where &ldquo;@('by k')&rdquo; may be implicit if @('k') is
  @('1').  Instead of the requirement in [4] above that the bound variable
  @('loop$-last-cdr') satisfy the @('type-spec'), variables @('loop$-lo'),
  @('loop$-hi'), and @('loop$-by'), which are bound respectively to @('i'),
  @('j'), and @('k'), are required to satisfy the @('type-spec').  A fourth
  requirement is that the last value tested must also satisfy the
  @('type-spec').  That last value tested is @('(+ loop$-lo loop$-by (*
  loop$-by (floor (- loop$-hi loop$-lo) loop$-by)))').  If you see a runtime
  guard violation involving variable @('loop$-lo'), @('loop$-hi'),
  @('loop$-by'), or @('loop$-final'), you can reasonably assume that you are
  seeing this variant of [4].</p>

  <p>But consider the raw Lisp @('loop') generated by the @('loop$') in the raw
  Lisp definition of @('foo'),</p>

  @({
  (loop for x of-type (satisfies spec) on lst sum (expr x)).
  })

  <p>For this @('loop') to execute without error we need to know that [5] every
  non-empty tail of @('lst') satisfies @('spec'), and [6] every non-empty tail
  @('x') of @('lst') is such that @('(expr x)') returns a number.</p>

  <p>So when ACL2's guard verification process encounters a @('sum$') like that
  in the logical @('defun') of @('foo'), it generates two additional guard
  conjectures as described above.  These are as mentioned above: [5] every
  element (or tail) satisfies the type-spec, and [6] the value of the
  @('loop$') body is acceptable to the @('loop$') operator.</p>

  @({
       (implies (and (warrant ...) ; see below                   ; [5]
                     (foo-guardp lst)
                     (member-equal newv (tails lst)))
                (spec newv))

       (implies (and (warrant ...) ; see below                   ; [6]
                     (foo-guardp lst)
                     (member-equal newv (tails lst)))
                (acl2-numberp
                 (apply$ (lambda$ (loop$-ivar) (expr loop$-ivar))
                         (list newv))))
  })

  <p>Notice the addition of hypotheses above of the form @('(warrant ...)').
  ACL2 adds such <i>@(see warrant) hypotheses</i> for function symbols that
  might be @(tsee apply$)'d during evaluation of a scion call (in this case,
  @('sum$')).</p>

  <p>In general, you may notice that ACL2 generates such ``special'' guard
  conjectures for all calls of @('FOR') @('loop$') scions, whether or not they
  stemmed from uses of @('loop$').  @('FROM/TO/BY') targets require that the
  bounds and step all satisfy the @('OF-TYPE') specification, and the
  @('APPEND') operator requires that the loop body generate a @(tsee
  true-listp) (instead of an @(tsee acl2-numberp) as required by the @('SUM')
  operator).</p>

  <h4>The Compromise Between Reasoning and Efficiency</h4>

  <p>The translation of @('loop$') expressions into formal terms reflects a
  compromise between facilitating compositional reasoning and efficient
  execution.</p>

  <p>One sign of that compromise is our use of scions to handle @('UNTIL') and
  @('WHEN') clauses.  As noted above, by translating</p>

  @({
  (loop$ for x in lst until ... when ... collect ...)
  })

  <p>into</p>

  @({
  (collect$ ... (when$ ... (until$ ... lst)))
  })

  <p>we're forcing the evaluation of the formal semantics to copy the target
  twice before collecting.  But it gives us the ability to reason
  compositionally about @('collect$'), @('when$'), and @('until$').  We could
  have defined a version of @('collect$') that took three @('lambda$')
  expressions, one to terminate the collection, one to filter for the elements
  we're interested in, and one to transform those elements into the values we
  wish to collect.  This would avoid copying upon evaluation but make it more
  difficult to reason.</p>

  <p>Another example of compositionality is to consider a simple @('loop$')
  over the @('IN') target @('(append a b)').  There are 8 different ways you
  can do a simple @('COLLECT') over an @('(append a b)') target,</p>

  @({
  (loop$ for x in (append a b) collect (expr x))
  (loop$ for x on (append a b) collect (expr x))
  (loop$ for x in (append a b) until (stop x) collect (expr x))
  (loop$ for x on (append a b) until (stop x) collect (expr x))
  (loop$ for x in (append a b) when (test x) collect (expr x))
  (loop$ for x on (append a b) when (test x) collect (expr x))
  (loop$ for x in (append a b) until (stop x) when (test x)
         collect (expr x))
  (loop$ for x on (append a b) until (stop x) when (test x)
         collect (expr x))
  })

  <p>Similarly, there are 8 ways to @('SUM') over an @('(append a b)') target,
  8 ways to @('APPEND') over an @('(append a b)'), and 4 ways each to
  @('ALWAYS') or @('THEREIS') over an @('(append a b)') target.  Thus, there
  are 32 different simple @('loop$')s over @('(append a b)').  And you can
  arrange to distribute the simple @('loop$') over the @('(append a b)') with
  just seven rewrite rules.</p>

  @({
  (equal (collect$ fn (append a b))
         (append (collect$ fn a)
                 (collect$ fn b)))

  (equal (sum$ fn (append a b))
         (+ (sum$ fn a)
            (sum$ fn b)))

  (equal (always$ fn (append a b))
         (and (always$ fn a)
              (always$ fn b)))

  (equal (thereis$ fn (append a b))
         (or (thereis$ fn a)
             (thereis$ fn b)))

  (equal (append$ fn (append a b))
         (append (append$ fn a)
                 (append$ fn b)))

  (equal (until$ fn (append a b))
         (if (exists$ fn a)
             (until$ fn a)
             (append a (until$ fn b))))

  (equal (when$ fn (append a b))
         (append (when$ fn a)
                 (when$ fn b)))

  })

  <p>Thus, you can reason about @('WHEN') and @('UNTIL') clauses without having
  to consider how they are used in the superior @('loop$') expression.</p>

  <p>To deal with fancy @('loop$') you need seven more rewrite rules, one for
  each fancy @('loop$') scion.  But since every simple @('loop$') can be
  expressed by an appropriate use of fancy scions, we could have translated
  every @('FOR') @('loop$') to fancy scions.  We chose to break
  compositionality here because we think simple @('loop$')s are most common and
  wanted to keep their semantics simple.  I.e., we compromised.</p>

  <p>By the way, if you want the prover to convert every simple scion to its
  fancy counterpart you could prove rewrite rules like that below.</p>

  @({
  (defthm convert-collect$-to-collect$+
    (implies (ok-fnp fn)
             (equal (collect$ fn lst)
                    (collect$+ `(lambda (loop$-gvars loop$-ivars)
                                  (,fn (car loop$-ivars)))
                               nil
                               (loop$-as (list lst)))))
    :hints (("[1]Goal"
             :expand ((tamep (cons fn '(x)))
                      (tamep (cons fn '((car loop$-ivars))))))))
  })")
other
(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>")
other
(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 application
 of @(see type-prescription) lemmas generally has fairly thorough knowledge of
 the types of all terms (see @(see type-prescription) for relevant
 background).</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.  See @(see type-reasoning) for relevant
 background for the following explanation.  If type reasoning alone is
 insufficient to prove some instance of a hypothesis, then the instance will
 not be proved by type reasoning 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>The discussion above may give the impression that a forcing round only
 takes place because of a failure to relieve a forced hypothesis.  A notable
 exception, however, is due to @(see linear-arithmetic).  Consider the
 following example:</p>

 @({
 (implies (not (equal 0 x))
          (or (< 0 x) (< x 0)))
 })

 <p>This is not a theorem; in particular, it fails when @('x') is @('nil').
 What is missing is the hypothesis, @('(acl2-numberp x)').  If you try to prove
 the displayed formula above and you look at the proof using @(':')@(tsee pso),
 you'll see the following.</p>

 @({
 But forced simplification reduces this to T, using the :executable-
 counterpart of FORCE and linear arithmetic.
 })

 <p>Thus, no specific rule created this forcing round (see also @(see
 forcing-round)).  Rather, ACL2 was able to prove the goal using linear
 arithmetic, but it needed to force the assumption that @('x') is a number.
 This is clear when we look at output for the forcing round:</p>

 @({
 [1]Goal, below, will focus on
 (ACL2-NUMBERP X),
 which was forced in
  Goal'
   by the linearization of
   (EQUAL 0 X).
 })

 <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)")
other
(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>")
other
(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 !>
 })")
other
(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 through backchaining.  Thus forward chaining is pro-active
 and backward chaining (rewriting) is reactive.</p>

 <p>The following example illustrates that forward chaining may be
 indispensable in a scenario with @(see free-variables), whose handling is
 quite weak with rewrite rules.</p>

 @({
 (defstub p0 (x) t)
 (defstub p1 (x) t)
 (defstub p2 (y) t)
 (defaxiom p0-implies-p1
   (implies (p0 x)
            (p1 x))
   :rule-classes :forward-chaining)
 (defaxiom p1-implies-p2
   (implies (p1 x)
            (p2 y)))
 ; ACL2 proves the following, but only because p0-implies-p1 is a
 ; :forward-chaining rule.  If p0-implies-p1 is instead a :rewrite
 ; rule, then the proof fails for the following event.
 (thm (implies (p0 x)
               (p2 y)))
 })

 <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 <see topic='@(url type-reasoning)'>type
 reasoning</see>, 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>")
other
(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 @(see 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>")
other
(defxdoc fourth
  :parents (nth acl2-built-ins)
  :short "Fourth member of the list"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(defxdoc fp
  :parents (df)
  :short "Floating-point and ACL2"
  :long "<p>ACL2 supports computation that uses floating-point operations; see
 @(see df).  If you are using an older Lisp, an attempt to build ACL2 may fail
 with an error complaining that &ldquo;feature :ieee-floating-point is
 missing&rdquo; [from the Lisp's @('*features*')].  <b>THIS ERROR INDICATES
 THAT ACL2 MAY BE UNSOUND WHEN BUILT ON THAT LISP!</b> If however you believe
 that your Lisp properly supports IEEE floating-point operations even though
 that feature is missing (e.g., quite possibly with older versions of CCL), you
 can avoid that build-time error by setting environment variable
 @('ACL2_FP_OK') to any non-empty string.  You might want to do that in a
 script that invokes your Lisp.</p>")
other
(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>")
other
(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>")
other
(defxdoc free-variables-examples-forward-chaining
  :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)))
 })")
other
(defxdoc free-variables-examples-rewrite
  :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)))
 })")
other
(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-system 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-system 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 !>
 })")
other
(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='https://acl2.org/doc/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 ensure 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 ensure 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 @(see 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>")
other
(defxdoc full-book-name
  :parents (books-reference)
  :short "Book naming conventions assumed by ACL2"
  :long "<p>See @(see pathname) for background on ACL2 pathnames.</p>

 <p>ACL2 defines a ``full-book-name'' to represent an absolute filename of a
 book.  This is typically a ``full-book-name string'' or simply
 ``full-book-string'': an absolute filename for the book.  At the end of this
 topic we mention a second representation, the <i>@(see sysfile)</i>; but until
 then, our discussion of full-book-names is restricted to the special (but
 common) case of full-book-strings.</p>

 <p>A full-book-name string 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>We conclude by discussing the other representation of full-book-names as
 promised above: the sysfile, which is a pair of the form @('(:kwd
 . "relpath")') where @(':kwd') is a @(see keyword) and @('"relpath"') is a
 relative pathname string.  See @(see sysfile) for a discussion of sysfiles.
 Here, we simply remark that sysfiles are used primarily by the implementation;
 as an ACL2 user you might never see one.  Sysfiles are used for
 full-book-names in @(see certificate) files and in various data structures in
 the ACL2 logical @(see world).</p>")
other
(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>")
other
(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).")
other
(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.  It may also be helpful to see @(tsee
 set-constraint-tracking) or to run the script below after doing
 @('(set-constraint-tracking t)').</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))))))
 })")
other
(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>")
other
(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'' (see @(see 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 @(see 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; if including "arithmetic/top-with-meta"
 isn't sufficient, you could try @('(include-book
 "arithmetic-5/top" :dir :system)').</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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(defxdoc gag-mode
  :parents (output-controls)
  :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
 })")
other
(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$))
 })")
other
(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>")
other
(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>")
other
(defxdoc gcl
  :parents (miscellaneous)
  :short "Tips on building and using ACL2 based on Gnu Common Lisp"
  :long "<p>See the @(see 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.  (This was some years ago,
 and the sizes of 28 and 29 can probably be increased now that Lisp
 implementations are 64-bit, with larger bounds on so-called fixnums.)</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))))
 })

 <p>7. You may want to set environment variable @('GCL_MEM_MULTIPLE') when
 running regression tests using ACL2 built on GCL, to keep memory from
 exceeding what is available.  Consider dividing 1.0 by the number of threads;
 so for example, for 4 threads (i.e., using &ldquo;@('-j 4')&rdquo; in your
 @('make') command), you may want to specify @('GCL_MEM_MULTIPLE=0.25').  But
 you can probably run with more threads (e.g., perhaps 20 threads or more on a
 64 MB machine) by instead doing a ``pooled memory run'', which may be
 performed as in the following example (bash syntax), as suggested by Camm
 Maguire.  Warning: the use of @('HOME') may change soon if it hasn't
 already.</p>

 @({
 HOME=/tmp ACL2=$(pwd)/saved_acl2 GCL_MULTIPROCESS_MEMORY_POOL=t \
   make -j 20 regression-fresh
 })

 <p>(Technical explanation: The reason for setting @('HOME') to directory
 @('/tmp') is to keep a so-called ``pool file'' local, since otherwise it will
 be on your home directory, which may be updated too infrequently if on a
 shared file system.)</p>")
other
(defxdoc geneqv
  :parents (introduction-to-the-theorem-prover break-rewrite)
  :short "the rewriter's generated equivalence relation"
  :long "<p>As the rewriter descends through a term, rewriting the subterms, it
  uses @(see congruence) rules to determine which @(see equivalence)s may be
  used to rewrite one subterm to another while ensuring that each rewrite
  maintains a given equivalence.  Generally speaking multiple equivalences may
  be used to rewrite subterms.  A ``generated equivalence'' or
  ``geneqv'' (pronounced ``genequiv'') is the way we encode which equivalences
  may be used by the rewriter at any given subterm position.</p>

  <p>The outline of this discussion is as follows.</p>

  <ul>

  <li>Basic Support for Equivalence Relations: a review of equivalence
  relations, refinement, and congruence</li>

  <li>Salient Facts about the ACL2 Rewriter: a review of how the rewriter
  works</li>

  <li>Using Congruence Rules to Generate Acceptable Equivalences for
  Subterms: an illustration of how congruence rules are used to determine the
  equivalences the rewriter is permitted to use</li>

  <li>Debugging Tools: How to see what equivalences are permitted while
  rewriting the current target and how to see how the set evolved as the
  rewriter descended from the top-level goal.</li>

  </ul>

  <h3>Basic Support for Equivalence Relations</h3>

  <p>If you do not know what the following ACL2 macro forms do, you should
  see their documentation.</p>

  <code>
  ; prove and store that eqv is an equivalence relation:

  (defequiv eqv)

  ; prove and store that the equivalence relation eqv1
  ; refines the equivalence relation eqv2

  (defrefinement eqv1 eqv2)

  ; prove and store that the equivalence relation eqv1 is a congruence relation
  ; for the kth argument of the function f, preserving the equivalence relation
  ; eqv2.

  (defcong eqv1 eqv2 (f x1 ... xn) k)
  </code>

  <p>An example of the last form is</p>

  <code>
  (defcong set-equal iff (member e x) 2)
  </code>

  <p>which essentially expands to</p>

  <code>
  (defthm set-equal-implies-iff-member-2
    (implies (set-equal x y)
             (iff (member e x)
                  (member e y)))
    :rule-classes (:congruence))
  </code>

  <p>(ACL2 actually generates a different variable name in place of @('y')
  above.)</p>

  <p>Helpful documentation topics include @(see equivalence), @(see
  refinement), @(see congruence), @(tsee defequiv), @(tsee defrefinement), and
  @(tsee defcong).</p>

  <h3>Salient Facts about the ACL2 Rewriter</h3>

  <ul>

  <li>Goals, which are represented as clauses, are simplified by rewriting each
  literal in turn, assuming the other literals false.</li>

  <li>When a term is rewritten (under some assumptions) the rewriter is given
  an @(see equivalence) relation to maintain, i.e., the output of the rewriter
  must be equivalent in that sense to the input, under the assumptions.</li>

  <li>The initial equivalence relation to be maintained while rewriting a
  literal is @(tsee iff).</li>

  <li>Each @(':')@(tsee rewrite) rule in ACL2 effectively concludes with a term
  of the form @('(eqv lhs rhs)'), where @('eqv') is an equivalence relation.
  Such a rule may be used to replace instances of @('lhs') by the corresponding
  instance of @('rhs'), and maintains the equivalence relation @('eqv').  But
  the rule is only applicable if @('eqv') <i>refines</i> the equivalence
  relation to be maintained by rewrite.  See @(see refinement).</li>

  <li>If the term to be rewritten is a function call, @('(fn a1 ... ak)'),
  the rewriter rewrites each @('ai') to, say, @('ai''), before applying rules
  to @('(fn a1' ... ak')').  To be more precise, when the ACL2 rewriter is
  asked to rewrite @('(fn a1 ... an)') maintaining some equivalence @('eqv'),
  it first rewrites each @('ai'), maintaining an equivalence generated from the
  congruence rules about how to rewrite the @('i')th argument of @('fn')
  maintaining @('eqv').  Suppose each @('ai') is thus rewritten to some other
  term @('ai'').  That is, @('(fn a1 ... an)') is transformed to @('(fn a1'
  ... an')') which is known to be @('eqv')-equivalent to @('(fn a1 ... an)').
  Then the rewriter applies all the @('eqv') rules it knows to @('(fn b1
  ... bn)').</li>

  <li>How the rewriter uses the known @(see congruence) rules to determine
  the equivalence relation to be maintained while rewriting each @('ai') is
  illustrated below.</li>

  <li>@('Equal') refines all equivalence relations.</li>

  <li>@('Equal') maintains all equivalence relations across all argument
  positions of all functions.</li>

  </ul>

  <h3>Using Congruence Rules to Generate Acceptable Equivalences for
  Subterms</h3>

  <p>In this section show how ACL2 generates the equivalence relation it will
  maintain when diving into subterms.  We do so by discussing a couple of
  contrived examples.  The actual script for these examples is in
  @('books/demos/geneqv.lisp').</p>

  <p>Our examples use the following functions.</p>

  <ul>

  <li>@('Len') is an ACL2 primitive that determines the number of elements
  in a list.</li>

  <li>@('(perm x y)') determines whether @('x') is a permutation of @('y'),
  i.e., whether each element that occurs in either @('x') or @('y') occurs in
  both the same number of times.  For example @('(perm '(A B A C) '(C B A A))')
  is true, but @('(perm '(A B A C) '(A B B C))') is false.</li>

  <li>@('(pairwise-iff x y)') determines whether corresponding elements of
  @('x') and @('y') are propositionally equivalent (i.e., @('IFF')-equivalent).
  For example, @('(pairwise-iff '(T NIL T) '(1 NIL A))') is true (since both
  @('1') and @('A') are non-@('NIL') and thus propositionally equivalent to
  @('T')), but @('(pairwise-iff '(T NIL T) '(1 NIL NIL))') is false.</li>

  <li>Both @('perm') and @('pairwise-iff') can be proved to be @(see
  equivalence) relations.</li>

  <li>Both @('perm') and @('pairwise-iff') are congruence relations for the
  first argument of @('len') that maintain @('equal')ity of @('len').

  <code>
  (defthm perm-implies-equal-len-1
    (implies (perm x y)
             (equal (len x)
                    (len y)))
    :rule-classes (:congruence))

  (defthm pairwise-iff-implies-equal-len-1
    (implies (pairwise-iff x y)
             (equal (len x)
                    (len y)))
    :rule-classes (:congruence))
  </code>
  </li>
  </ul>

  <p>Now consider proving</p>

  <code>
  (defthm example-thm-1
    (equal (len (isort (norml x)))
           (len x))
    :rule-classes nil)
  </code>

  <p>Before we start you should understand that there are many ways to prove
  this little theorem.  The most straightforward is just to prove that
  @('(len (isort x))') is @('(len x)') and to prove @('(len (norml x))') is
  @('(len x)').  In this case, where the functions involved are @('isort') and
  @('norml'), those theorems are easy to prove.  But for some functions in
  those roles of a problem like this it is easier to appeal to the properties
  of certain equivalence relations.  That's what we'll do here.</p>

  <p>If you run the @('defthm') above, the prover (after preprocessing)
  eventually calls the rewriter on the @('equal') term, requiring it to
  maintain @('iff').  The rewriter then dives into the two arguments, rewriting
  @('(len (isort (norml x)))') first, maintaining @('equal')ity.</p>

  <p>The rewriter then dives into the first argument of the @('len') term,
  @('(isort (norml x))').  The congruence rule @('perm-implies-equal-len-1')
  above tells it that @('equal')ity of the @('len') term is maintained if the
  first argument is rewritten maintaining the @('perm') equivalence.  In
  addition, the congruence rule @('pairwise-iff-implies-equal-len-1') tells it
  that @('equal')ity of the @('len') term is also maintained if the first
  argument is rewritten maintaining the @('pairwise-iff') equivalence.</p>

  <p>Thus, when rewriting @('(isort (norml x))') the rewriter can use any
  rewrite rule that maintains @('perm'), any rewrite rule that maintains
  @('pairwise-iff'), and, of course, any rewrite rule that maintains
  @('equal').  In addition, of course, it can use any rewrite rule that
  maintains a refinement of any of these equivalence relations.  This
  ``generated equivalence'' or ``geneqv'' is denoted by a set containing the
  named equivalence relations and the justifying congruence rules.</p>

  <p>The geneqv just derived is represented internally as</p>

  <code>
  ((5658 PAIRWISE-IFF
         :CONGRUENCE PAIRWISE-IFF-IMPLIES-EQUAL-LEN-1)
   (5651 PERM
         :CONGRUENCE PERM-IMPLIES-EQUAL-LEN-1))
  </code>

  <p>Ignoring the two numbers, we see two pairs, each naming an equivalence
  relation and the @(see rune) that justifies its use here.  The numbers are
  session-specific indices uniquely associated with the two runes that allow
  ACL2 to determine quickly if the runes are enabled.  Note that we do not
  include an entry for @('EQUAL') since it maintains every equivalence relation
  in every argument position of every function.  Indeed, if you see a geneqv of
  @('NIL') it means @('EQUAL') is the only acceptable equivalence relation in
  that context.</p>

  <p>Debugging tools in ACL2 typically display the geneqv above as</p>

  <code>
  ((PAIRWISE-IFF PAIRWISE-IFF-IMPLIES-EQUAL-LEN-1)
   (PERM PERM-IMPLIES-EQUAL-LEN-1))
  </code>

  <p>or even</p>

  <code>
  (PAIRWISE-IFF PERM).
  </code>

  <p>We discuss debugging tools that display geneqvs below.</p>

  <p>But what does this geneqv buy us during this proof?  Recall where we were
  in the proof discussed above.  We're rewriting @('(isort (norml x))')
  maintaining @('(PAIRWISE-IFF PERM)').  If the user had proved the following
  two rewrite rules</p>

  <code>
  (defthm perm-isort                ; isort preserves perm
    (perm (isort X) X))

  (defthm pairwise-iff-norml        ; norml preserves pairwise-iff
     (pairwise-iff (norml x) x))
  </code>

  <p>then the rewriter would replace @('(isort (norml x))') by @('(norml
  x)') using the first rule, since @('perm') is a refinement of the geneqv, and
  then the rewriter would rewrite that and replace it by @('x') using the
  second rule, since @('pairwise-iff') is also a refinement of the geneqv.
  Note that neither of these replacements preserve @('equal')ity, but they are
  permitted because they preserve the @('equal')ity of the @('len')s.</p>

  <p>Thus, @('(equal (len (isort (norml x))) (len x))') has been simplified to
  @('(equal (len x) (len x))') which further simplifies to @('t') and the proof
  is done.</p>

  <p>The Community Book @('"books/demos/geneqv-test-book.lisp"') (which
  executes the commands in books/demos/geneqv-test-input.lsp) contains this and
  other examples.</p>

  <h3>Debugging Tools</h3>

  <p>Generated equivalence relations are never mentioned or displayed in the
  prover output.  But of course they are crucial since they determine which
  rewrite rules can be used.  If a rule was expected to be used in a proof or
  proof attempt but was not used it might be because the rule's equivalence
  relation failed to be a refinement of the geneqv in effect when the intended
  target was encountered.  If @(tsee brr) is enabled and a @(tsee monitor)ed
  rule is tried by the rewriter but does not fire because it failed the
  refinement test, a @(see break-rewrite) interactive break occur.  See @(see
  refinement-failure) for some advice for how you might respond to such a
  failure.</p>

  <p>From within a break-rewrite break the @(tsee brr-commands) @(':path') will
  print the ``path'' from the current top-level goal down to the call of the
  rewriter on current @(':target') term.  Like a call stack, the path is
  composed of ``frames,'' most of which describe calls of the rewriter but some
  of which are calls of other system functions (like the @(tsee
  linear-arithmetic) procedure) that orchestrate other calls to the rewriter.
  As of Version  8.6, each frame of the @(':path') that describes the attempt
  to apply a particular rewrite rule will display the name of the equivalence
  relation used by the rule (unless that name is @('equal')).  Every frame
  describing a call of the rewriter includes the geneqv to be maintained as the
  target is rewritten (unless the geneqv is @('nil') which denotes the
  @('equal')ity relation).  The noted exceptions are intended to shorten the
  output in the most common cases: rewriting with @('equal') and maintaining
  equality.</p>

  <p>In addition, from within such a break the brr-command @(':geneqv') will
  print the geneqv for the current target.</p>")
other
(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>")
other
(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
 })")
other
(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>")
other
(defxdoc gentle-introduction-to-acl2-programming
  :parents (start-here)
  :short "A Gentle Introduction to ACL2 Programming"
  :long "<h1>A Gentle Introduction to ACL2 Programming</h1>

 <h1><i>by</i></h1>
 <h1>J Strother Moore</h1>

 <h2>Abstract</h2>

 <p>ACL2 is a logic and programming language in which you can model computer
 systems, together with a tool to help you prove properties of those
 models. &ldquo;ACL2&rdquo; denotes &ldquo;A Computational Logic for
 Applicative Common Lisp&rdquo;.  The ACL2 programming language is a subset of
 <i>side-effect free</i> Common Lisp.  Mathematically speaking, all ACL2
 programs are functions.  When two calls of a function supply the same objects
 as inputs the calls return the same results.  If all you want to do is define
 ACL2 functions and run them, you don't need to know how to use ACL2 as a
 theorem prover.  This introduction is all you need.</p>

 <h2>Getting Started</h2>

 <p>If you haven't installed ACL2 on your machine, do so, by following the
 instructions at &ldquo;Obtaining, Installing, and License&rdquo; on the <a
 href='https://www.cs.utexas.edu/users/moore/acl2'>ACL2 Home Page</a>.  As
 those instructions make clear, to run ACL2 you'll need a Common Lisp
 implementation.  The instructions name several suitable ones.</p>

 <p>In addition to the @(see installation) instructions, the Home Page has a
 wealth of documentation.  You should visit &ldquo;The User's Manuals&rdquo;.
 There you'll see several versions of the manual, depending on whether you want
 information about utilities developed by users.  But we recommend that
 newcomers just look at the basic &ldquo;ACL2 User's Manual&rdquo;.  Explore it
 briefly just so you know how to find more information.  For example, type
 &ldquo;defun&rdquo; into the Jump to box and hit return.  You'll see details
 of how to define functions and there are many links in that discussion to
 related topics.  But don't try to understand @('defun') by reading all that.
 The manual is basically for users who are looking for technical information
 about features they basically know how to use.  Having learned how to explore
 the manual, put it aside for now and focus on this document!</p>

 <p>The interface to the ACL2 system is a read-eval-print loop.  It prints a
 prompt.  You type some command and hit return.  It reads and evaluates your
 command.  It prints the results.  And then it prompts you for your next
 input.</p>

 <p>You could use ACL2 with no other interface.  But most users prefer an
 environment in which they can prepare a command by editing the text before
 submitting it.  We use an Emacs shell buffer for that.  Other users use <see
 topic='@(url acl2-sedan)'>ACL2s</see>, which is an Eclipse plug-in.  This
 guide doesn't discuss the interface further and we just assume you can submit
 commands and see the output.  The examples we provide are from our Emacs
 interface.</p>

 <p>ACL2 is implemented (largely) in ACL2.  That is, almost all the system code
 is written in the ACL2 subset of Common Lisp.  The examples provided here were
 prepared under ACL2 Version 8.5.  Your output should be logically equivalent
 though the text may look a little different.</p>

 <p>Now fire up your ACL2.  You should see a prompt that looks like this</p>

 <code>
 ACL2 !&gt;
 </code>

 <p>Type &ldquo;:program&rdquo; and a return.</p>

 <code>
 ACL2 !&gt;:program
 ACL2 p!&gt;
 </code>

 <p>The @(':program') command tells ACL2 that subsequent definitions should merely be treated as
 ACL2 programs and not admitted into the logic.  (To admit a program into the logic requires proving
 that the program terminates.  We do not want to deal with proofs of any sort in this guide, so
 we'll stay in @(':program') mode.)</p>

 <p>Now type &ldquo;@('(+ 2 2)')&rdquo;.  You should see the answer, @('4')
 printed on the next line.  This illustrates the basic behavior of ACL2's
 read-eval-print loop.  The display below shows several other examples too.</p>

 <code>
 ACL2 !&gt;:program
 ACL2 p!&gt;(+ 2 2)
 4
 ACL2 p!&gt;(+ 1 2 3 4)
 10
 ACL2 p!&gt;(car '(hello world))
 HELLO
 ACL2 p!&gt;(cdr '(hello world))
 (WORLD)
 ACL2 p!&gt;(cons 'hello '(world))
 (HELLO WORLD)
 ACL2 p!&gt;
 </code>

 <p>Sometimes computations cause errors, most commonly due to type violations
 or resource limitations.  See the sections Type Errors and Stack Overflow
 below.</p>

 <p> Here is an ACL2 program that takes a linear list of numbers and constructs
 a linear list of their squares.  We've annotated it with Lisp comments.  ACL2
 ignores the comments.  We'll explain the syntax later.  For now we'll just
 interpret what this whole definition means.</p>

 <code>
 (defun square-all (x)

 ; Make a list of the squares of the elements of the list x.

   (cond
    ((endp x)                       ; If x is empty,
     nil)                           ; return the empty list.

    (t                              ; Otherwise,
     (cons (* (car x) (car x))      ; square the first element and
           (square-all (cdr x)))))) ; cons it onto the front of
                                    ; the squares of the rest.
 </code>

 <p>If you aren't sure what a &ldquo;linear list&rdquo; is just hang in and
 we'll get to it.  But you've probably figured out that @('nil') is the empty
 list, that @('cons') constructs a list by &ldquo;adding&rdquo; an element to
 the front of another list, that @('car') returns the first element of a
 non-empty list, and that @('cdr') returns all but the first element of a
 non-empty list.  Those deductions are right, as far as they go.</p>

 <p>Here is what it looks like if you submit the @('square-all') definition
 to the read-eval-print loop.  We have omitted most of the previous commands and their
 output, and we have omitted the comments we included in the display above.</p>

 <code>
 ACL2 !&gt;:program
 ...
 ACL2 p!&gt;(cons 'hello '(world))
 (HELLO WORLD)
 ACL2 p!&gt;(defun square-all (x)
   (cond ((endp x) nil)
         (t (cons (* (car x) (car x))
                  (square-all (cdr x))))))

 Summary
 Form:  ( DEFUN SQUARE-ALL ...)
 Rules: NIL
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
  SQUARE-ALL
 ACL2 p!&gt;
 </code>

 <p>
 Once @('square-all') is defined we can run it.  Here are some tests.</p>
 <code>
 ACL2 p!&gt;(square-all '(1 2 3 4 5))
 (1 4 9 16 25)
 ACL2 p!&gt;(square-all nil)
 NIL
 ACL2 p!&gt;(square-all '(-9 3/4 #c(0 5)))
 (81 9/16 -25)
 ACL2 p!&gt;
 </code>

 <h2>Data Types</h2>

 <p>
 ACL2 supports five very simple but rather abstract types of data: </p>
 <ul>
 <li>numbers,</li>
 <li>characters,</li>
 <li>strings,</li>
 <li>symbols (which includes the two Booleans @('T') and @('NIL')), and</li>
 <li>pairs or &ldquo;conses&rdquo;.</li>
 </ul>

 <p>Objects of each type are distinct.  That is, no number is a character or a
 string or a symbol or a pair.  Etc.</p>

 <p>
 All of these objects are &ldquo;first class&rdquo; in the sense that you can pass them
 in as values to functions, return them as values from functions, and store
 them in lists and trees.</p>

 <p>
 Many operators are provided for each type.  Each operator is a
 <i>function</i>.  </p>

 <p>
 <i>No ACL2 operator or function can modify, mutate, or otherwise alter the
 objects passed in as arguments.</i></p>

 <p>Since you're probably more familiar with conventional programming languages
 than functional (side-effect free) ones, let's talk operationally for a
 moment.  (This is a disservice to you!  The operational view is more
 complicated than the abstract mathematical view!)  ACL2 is implemented on top
 of a von Neumann architecture.  So what happens &ldquo;behind the
 scenes&rdquo; when the ACL2 function @('cons') is called on @('4') and @('5')?
 Mathematically it returns the pair &lt; @('4'), @('5') &gt; which is printed
 in ACL2 as @('(4 . 5)').  But operationally, some memory is allocated for a
 new object, then the representations of 4 and 5 are stored in two
 fields (called the <i>car</i> and <i>cdr</i> fields) of that object, that
 region of memory is effectively tagged to indicate that it represents a
 @('cons') pair, and a pointer to the newly allocated object is returned as the
 result of the call of @('cons').  When that result is printed by ACL2 it
 appears as @('(4 . 5)').  The italicized sentence above means <i>nothing you
 can do in ACL2 will change the contents of that newly allocated memory.</i> In
 most programming languages you could invoke some procedure or method to
 overwrite the contents of the <i>car</i> field of that object, changing it
 from @('4') to @('3').  No such procedure or method exists in ACL2.  The
 object returned by that call of @('cons') will print as the pair @('(4 . 5)')
 &mdash; will <i>be</i> the pair @('(4 . 5)') &mdash; for as long as you have
 access to the pointer returned by that call of @('cons').</p>

 <p>
 ACL2 expressions are just nests of function calls.  For example
 @('(factors (+ x (* 3 y)))') calls the function @('factors')
 on the value of <i>x+3y</i>.  (We define @('factors') below to
 return the list of prime factors of its input.)  The functions
 @('+') and @('*') are examples of functions that
 operate on numbers.</p>

 <p>
 Before we discuss ACL2 expressions further we must discuss the
 important issue of how you write down constants of each of the five types.</p>

 <p> A few examples suffice to illustrate the common ways to enter numeric
 constants: @('123'), @('22/7') and @('#c(3 5)').  Note that ACL2 provides
 &ldquo;infinitely precise&rdquo; rational numbers like @('1/3') and @('22/7').
 These are not floating point numbers; we don't provide floating point numbers.
 The rational @('2/3') could also be written @('4/6') &mdash; they are two
 different ways of writing the same number.  The ACL2 number @('#c(3 5)') is
 more conventionally written as the complex number <i>3+5i</i>.  ACL2 also
 supports writing numeric constants in binary, octal and hexadecimal notation,
 but we do not use that here.</p>

 <p>We will list some operations on numbers later.</p>

 <p> Here are examples of how to write character objects: @('#\A') and
 @('#\a') and @('#\Space').  Character objects are primarily used to build up
 strings.  While ACL2 provides functions for manipulating character objects (e.g., to
 recover their ASCII codes) we won't be using them here.</p>

 <p> Strings are delimited by the double quote mark, e.g., @('"This is an
 error message."') Again, there are functions more manipulating strings but we
 won't use them in this guide.</p>

 <p> This leaves us with symbols and conses.  Two symbols are easy to
 understand because they have counterparts in most programming languages:
 @('T') is a symbol but it is also ACL2's Boolean &ldquo;true&rdquo; object.
 @('NIL') is a symbol and is ACL2's Boolean &ldquo;false&rdquo; object.  When
 an ACL2 predicate is said to be false, we mean the predicate returns @('NIL').
 When an ACL2 predicate is said to be true, it usually means it returns @('T'),
 but more precisely it means it returns anything but @('NIL').  Oddly, Lisp and
 ACL2 also use the symbol @('NIL') as the &ldquo;empty list&rdquo;.</p>

 <p>
 Before we discuss other ACL2 functions however we must deal at length with
 symbols and conses.  Many first-time Lisp programmers do not really
 understand the idea of symbols as data or the idea of lists and trees as
 data.</p>

 <h2>Symbols</h2>

 <p> Symbols are sequences of alphabetic letters, signs and digits.  So @('X'),
 @('X*'), and @('ABC23') are symbols.  So are @('CAR'), @('IF'), and
 @('TRUE-LISTP').  Note that dashes and other signs do not &ldquo;break&rdquo;
 symbols into pieces.  @('TRUE-LISTP') is one symbol, not two symbols separated
 by a minus sign.</p>

 <p> Technically, a symbol can contain any sequence of characters and there are
 rules for writing symbols down so as to distinguish them from other constants.
 Using certain &ldquo;escape&rdquo; conventions you can actually write symbols
 containing spaces and parentheses, symbols composed entirely of digits, and
 symbols with other &ldquo;weird&rdquo; characters.  But we will not go into
 these conventions in this introduction.  We will limit ourselves to symbols
 that &ldquo;look like&rdquo; what you probably expect.  Most often, symbols
 start with an alphabetic character and then contain just alphabetic
 characters, signs and digits.  The first space, newline or parenthesis you
 encounter while reading a symbol marks the end of the symbol and isn't part of
 it.</p>

 <p> All programming languages (except binary machine code) have symbols at the
 syntactic level.  Symbols are used to denote variables, functions, operations,
 keywords, etc., in the syntax of most programming languages.  This is
 true in ACL2 too.  But ACL2 is a little different in that it also provides
 symbols as data objects.  That is, in addition to familiar data objects like
 numbers and strings, ACL2 provides symbols as a kind of data structure that
 can be manipulated.  For example, a symbol can be converted to a string
 object, or decomposed into its constituent characters, or several symbols can
 be concatenated to create a longer symbol.  But in this introduction we will
 just pass symbols around, compare them to other objects, and create
 lists (conses) containing symbols as elements.</p>

 <p> As noted, @('T') and @('NIL') are symbols with special significance.  They
 are our &ldquo;Booleans&rdquo; data objects and @('NIL') is used as the
 &ldquo;empty list&rdquo;.</p>

 <p> Symbols are more complicated than described above because in addition to
 their names they belong to &ldquo;packages.&rdquo; For example, there might be
 a symbol named @('ABS') in a package named @('"MATH"') and a symbol named
 @('ABS') in a package named @('"VECTORS"').  There is always one
 &ldquo;current package&rdquo; in ACL2 &mdash; you can select any package as
 the current package.  If @('"MATH"') were the current package, then when you
 write @('ABS') you denote the symbol @('ABS') in the @('"MATH"') package.
 If you mean the symbol @('ABS') in the @('"VECTORS"') package you would have
 to write @('VECTORS::ABS').  We will not use packages here.</p>

 <p> There is a special package called the @('"KEYWORD"') package.  The
 symbol @('ABS') in the @('"KEYWORD"') package can, of course, be written
 @('KEYWORD::ABS').  But special syntactic sugar also allows us to write
 @(':ABS') for that symbol.</p>

 <p> When we write symbols, case is unimportant (unless that previously
 mentioned &ldquo;escape&rdquo; convention is used).  When reading a symbol all
 characters are all uppercased.  That is, ACL2 reads the symbol @('x') as
 @('X').  The symbol @('The') is read as @('THE') and @('True-Listp') is read
 as @('TRUE-LISTP').  Thus, the choice of whether to write a symbol in
 uppercase, lowercase, or some mixture of cases is just a stylistic one.</p>

 <code>
 ACL2 p!&gt;'(Here is a list of SymBols!)
 (HERE IS A LIST OF SYMBOLS!)
 ACL2 p!&gt;'(This list contains a |Weird Symbol|)
 (THIS LIST CONTAINS A |Weird Symbol|)
 ACL2 p&gt;
 </code>

 <p>
 ACL2 provides ways to construct symbols from strings, ways to construct
 strings from lists of character objects, and ways to construct character
 objects from integers.  But elementary ACL2 programs rarely construct new
 symbols, strings and characters dynamically.  The symbols, strings and
 characters manipulated during most program executions are entered initially
 in the input data (e.g., by reading a command line or input file).
 Therefore, we do not bother to describe how to &ldquo;create&rdquo; symbols, strings
 and characters and none of our examples create these objects dynamically.</p>

 <h2>Lists</h2>

 <p>We first discuss how to write down &ldquo;cons pairs&rdquo; and &ldquo;
 list objects&rdquo;.  Later we will describe the operations on them.  There
 are many ways to write the same list constant.  This should not be surprising;
 the same thing is true of numeric constants.  Consider the fact that @('123'),
 @('000123'), @('+0123'), @('246/2') and @('#b1111011') are all ways to write
 down the same numeric constant.  The form you choose when writing a numeric
 constant is up to you and is often chosen to emphasize some aspect of the
 data.  For example, I might pad an integer with insignificant 0s to emphasize
 that it fits in a field of six digits, or I might unnecessarily write a + sign
 on the only positive integer in a data set.  Like numbers in other programming
 languages, lists are so common in ACL2 that there are many ways to write the
 same list constant but the choice of &ldquo;style&rdquo; is just that:
 stylistic.</p>

 <p> Most programming languages support the idea of some kind of record
 structure with fields containing other objects.  The only such record
 structure in ACL2 is the <i>ordered pair</i> or <i>cons pair</i>.  A cons pair
 is just a pair of two objects.  Sometimes we call a cons pair a &ldquo;list
 pair&rdquo; or a &ldquo;dotted pair&rdquo; or simply a &ldquo;list.&rdquo;</p>

 <p>
 Any two objects may be put together into a cons pair.  The cons pair
 containing the integer @('1') and the integer @('2') might be drawn as:</p>
 <code>
            *
           / \
          1   2
 </code>
 <p>
 or might be written in Cartesian coordinate notation as &lt;@('1'),@('2')&gt;.  But in ACL2
 it is written as the object @('(1 . 2)').  This is a single cons object in
 ACL2, with two integer objects as constituents.  The left-hand constituent
 is called the <i>car</i> of the pair.  The right-hand constituent is called the
 <i>cdr</i>.</p>

 <p>
 The tree we might draw as</p>
 <code>
            *
           / \
          1   *
             / \
            2   3
 </code>
 <p>
 or write in coordinate notation as &lt;@('1'), &lt;@('2'), @('3')&gt;&gt;, in
 ACL2 is written the object @('(1 . (2 . 3))').  The car of this object is the
 integer @('1').  The cdr of this object is the object @('(2
 . 3)').</p>

 <p>
 Similarly,</p>
 <code>
            *
           / \
          /   \
         *     *
        / \   / \
       1   2 3   4
 </code>

 <p> or &lt;&lt;@('1'), @('2')&gt;,&lt;@('3'), @('4')&gt;&gt; is written
 @('((1 . 2) . (3 . 4))').  Suppose <i>x</i> is the cons object just mentioned.
 Then the car of <i>x</i> is the object @('(1 . 2)') and the cdr is the object
 @('(3 . 4)').  Obviously, the car of the car of <i>x</i> is @('1').  The cdr
 of the car of <i>x</i> is @('2'), etc.</p>

 <p>
 The notation we are using to write list objects is called <i>dot
 notation</i>. It is a straightforward translation of the familiar
 coordinate notation in which parentheses replace the brackets and a dot
 replaces the comma.</p>

 <p>
 But there are other ways to write these conses.  This should not be
 surprising.  How many ways can you think of to write the number
 @('5')?  There are an infinite number!  @('5'),
 @('05'), @('005'), @('+000005'), etc., not to mention
 possibly @('#B101') and others.  Those are all just &ldquo;syntactic
 sugar&rdquo; for denoting one familiar object.  The sugars above might be
 described as &ldquo;you can add a leading @('0')&rdquo; and &ldquo;you can add a
 single leading plus sign on a positive number.&rdquo;</p>

 <p>
 Similarly, ACL2 has two rules that allow us to write cons pairs in
 a variety of ways.  The first rule provides a special way to write trees
 like:</p>
 <code>
           *
          / \
         1   nil
 </code>

 <p> namely, you can write @('(1 . nil)') or you can write @('(1)').  That is:
 if a cons pair has @('NIL') as its cdr, you can drop the &ldquo;dot&rdquo; and
 the @('NIL').</p>

 <p>
 The second rule provides a special way to write a cons pair that contains
 another cons pair in the cdr.  The rule allows us to write @('(')<i>x</i> @('. (...))')
 as @('(')<i>x</i> @('...)').  That is, when the cdr is a
 cons, you can drop the dot and the pair of balanced parentheses following it.</p>

 <p>
 Thus, the tree</p>
 <code>
           *
          / \
         1   *
            / \
           2   *
              / \
             3   nil
 </code>
 <p>
 can be written in any of the following ways.</p>
 <code>
 (1 . (2 . (3 . nil)))
 (1 . (2 . (3)))
 (1 . (2 3))
 (1 2 3)
 </code>
 <p>
 It can also be written in many other ways, e.g., @('(1 2 . (3 . nil))') and
 @('(1 . (2 3))').</p>

 <p>
 Binary trees that terminate in @('nil') on the right-most branch,
 such as the one above, are
 often called <i>linear lists</i>.  The <i>elements</i> of a list are the
 successive cars along the &ldquo;cdr chain.&rdquo;  That is, the elements are the car,
 the car of the cdr, the car of the cdr of the cdr, etc.  The elements of the
 list above are @('1'), @('2'), and @('3'), in that
 order.  If we let <i>x</i> denote that tree, i.e., let <i>x</i> be
 @('(1 2 3)'), then the car of <i>x</i> is @('1').  The cdr
 of <i>x</i> is the linear list @('(2 3)').  The car of the cdr of
 <i>x</i> is thus @('2').  The cdr of the cdr of <i>x</i> is the
 linear list @('(3)').  The car of the cdr of the cdr of <i>x</i>
 is @('3').  And the &ldquo;third cdr&rdquo; of <i>x</i> is @('nil').</p>

 <p>The linear list @('(A (B C D) E)') has three elements.  @('B') is not an
 element of that list, it is an element of an element.</p>

 <p>
 The following is a linear list of pairs.</p>

 <code>
      *
     / \
    *   \
   / \   \
  A   1   *
         / \
        *   \
       / \   \
      B   2   *
             / \
            *   \
           / \   \
          C   3   nil
 </code>
 <p>
 This list can be written @('((A . 1) (B . 2) (C . 3))').  In full
 dot notation it is written</p>
 <code>((A . 1) . ((B . 2) . ((C . 3) . NIL))).
 </code>

 <p>
 By the way, lists such as the one above are so common they
 have a name.  They are called <i>association lists</i> or
 <i>alists</i> and are used as keyed tables.  The list above associates
 the key @('A') with the value @('1'), the key @('B')
 with the value @('2'), etc.  Later we show functions for manipulating
 alists.</p>

 <p>
 Lists are often used to represent more elaborate data structures.  For
 example, an &ldquo;account&rdquo; might consist of a name, an id number, a
 balance and a list of transactions, laid out like this:</p>
 <code>
         *
        / \
       /   \
      /     \
     *       *
    / \     / \
   /   \   /   \
 name  id bal  trans
 </code>
 <p>
 An example of an account object might be</p>
 <code>
 (("John Smith" . 123456789)    ; Name and id
  .
  (1254 .                       ; balance in cents
    ((DEPOSIT (1 21 1999) 1000) ; transactions
     (WITHDRL (1 30 1999)  850)
     (WITHDRL (2  5 1999)  215))))
 </code>

 <p>Rather than refer to these four components in terms of the @('car') and
 @('cdr') of the account object most programmers would define functions with
 application-specific names like @('account-name'), @('account-id'), etc.
 Instead of building each account object with a nest of @('cons') expressions
 they would define @('(make-account name id bal trans)') to do the consing.</p>


 <h2>Expressions</h2>

 <p>We've seen that the basic idiom for defining a new function in ACL2 is to
 write</p>

 <code>
 (defun f (v1 ... vn) body)
 </code>

 <p>where @('f') is the name of the function, the @('vi') are its input
 parameters, and @('body') is an expression that computes the value of the
 function in terms of the parameters.  The <i>n</i> parameters must be distinct
 variable names and we say that <i>n</i> is the <i>arity</i> of the new
 function @('f').  But what are expressions?</p>

 <p>With a few exceptions, an expression is either</p>

 <ul>
 <li>a variable symbol,</li>

 <li>a constant expression,</li>

 <li>a call of a function of arity <i>n</i> on <i>n</i> argument
 expressions (sometimes called the <i>actuals</i>).</li>

 </ul>

 <p>Variable symbols are written in the same way that symbol objects are
 written, except @('T'), @('NIL'), and keywords may not be used as variable
 symbols.  Examples of variable symbols are thus @('X'), @('k'), @('temp3'),
 and @('init-val').</p>

 <p>There are two kinds of constant expressions: those that can just be written
 as ordinary objects and those that must be quoted.  Character objects,
 strings, numbers, @('T'), @('NIL'), and keywords are of the first kind.  They
 may be used as constant expressions without any additional signifying mark.
 All other symbols and all list objects must be preceded by a single quote
 mark (') to be used as constants in an expression.  Examples of constant
 expressions of the first kind are thus @('#\Space'), @('"EOF Error"'),
 @('128'), @('T'), @('NIL'), and @(':element').  Constant expressions of the
 second kind include @(''X'), @(''HELLO'), and @(''(MON WED FRI)').</p>

 <p>Function calls are written by writing an open parenthesis, the name of the
 function and the <i>n</i> argument expressions, all separated by whitespace,
 followed by a close parenthesis.  For example @('(cons (* (car x) (car
 x)) (square-all (cdr x)))') is a function call of the function @('cons') on
 two argument expressions.  The first argument is a call of @('*') on two
 expressions, both of which are calls of @('car') on the variable symbol
 @('x').  The second argument to the call of @('cons') is @('(square-all (cdr
 x))'), which is a call of @('square-all') on a call of @('cdr') on @('x').</p>

 <p>
 Consider the list object @('(CAR X)'), which we can draw as</p>
 <code>
      *
     / \
    CAR \
         *
        / \
       X  NIL.
 </code>

 <p>This object can be written as @('(CAR X)').  But that is also the way we
 write the expression that denotes a call of the function @('CAR') on @('X').
 So if we want to use that object in an expression we have to quote it to make
 it clear we mean the object rather than the expression.</p>

 <p>We have said that an expression is either a variable, a constant, or a
 function call of a function symbol of arity @('n') on @('n') argument
 expressions.  But there are exceptions to this simple characterization of
 expressions.  One exception is that some functions appear to take varying
 numbers of arguments.  For example, ACL2 allows @('+') and @('*') to take more
 than two arguments.  So @('(+ (* x x) (* 2 x y) (* y y))') is allowed.  We'll
 note other such functions when we use them here.  Another exception is a
 special notation for nested if-then-else expressions described below.  These
 exceptions are actually facilitated by a <i>macro</i> facility allowing the
 user to define new notation, but we will not discuss macros here even though
 we will use and explain some macros in our examples.  Finally, ACL2 permits
 calls of unnamed functions, called <i>lambda expressions</i>, but we won't use
 them explicitly in this introduction.  The reason we say
 &ldquo;explicitly&rdquo; is that we will use so-called @('let') expressions to
 introduce some local temporary variables and ACL2 understands
 @('let') expressions as applications of lambda expressions.  We'll explain
 when we introduce @('let').</p>

 <p>An example expression is</p>

 <code>
 (cons (cons 'square-all (cons x nil))
       (cons '=
             (cons (square-all x) nil)))
 </code>

 <p>provided @('square-all') has been defined as a function of arity 1.  Note
 that case is actually unimportant in symbols, whether they are function or
 variable names or data objects.  Unless special conventions are employed all
 symbols are read in uppercase.</p>

 <p>Expressions have <i>values</i> computed with respect to an environment
 assigning values to variable symbols.  For example, if @('square-all') is
 defined as previously shown and @('x') has the value @('(1 2 3)') then the
 value of the expression above is</p>

 <code>
 ((SQUARE-ALL (1 2 3)) = (1 4 9)).
 </code>

 <p>Here is the algorithm for determining the value of an expression in an
 environment. The value of a variable is just looked up in the environment.
 The value of a constant expression is the obvious object.  The value of a call
 of a defined function is computed by (a) evaluating the <i>n</i> argument
 expressions to obtain a sequence of <i>n</i> objects, (b) creating a new
 environment in which the function's <i>n</i> parameters are assigned those
 respective objects, and then (c) evaluating the body expression of the
 function in that new environment.  The value of a call of a primitive
 function, like @('*') or @('cons'), is determined by running special code on
 the values of the arguments.</p>

 <p>For example, suppose we have added this definition</p>

 <code>
 (defun sq (x) (* x x))
 </code>

 <p>and we are in an environment where @('x') has value @('5').  Then here is
 an annotated computation of the value of @('(sq (+ 1 x))').</p>

 <code>
 (sq (+ 1 x))
 =                ; evaluate argument of sq, when x = 5
 (sq 6)
 =                ; evaluate body of sq, when x = 6
 36.
 </code>

 <h2>Primitive Functions</h2>

 <p>The ACL2 system starts up with over eight thousand known functions, 32 of
 which are primitive (defined by special code rather than definitions).  The
 rest are defined.  Here is a brief summary of a few useful primitives.  We
 have biased this list to encourage merely integer arithmetic and list
 processing.  Some of the functions mentioned below are not actually primitive
 but are defined as simple compositions of primitives.  For example, @('(natp
 x)') is defined to be @('(and (integerp x) (<= 0 x))').  Other
 &ldquo;functions&rdquo; mentioned below are actually macros that expand into
 primitive expressions.</p>

 <ul>

 <li>@('(EQUAL x y)') &mdash; @('t') if @('x') and @('y') are the same
 object and @('nil') otherwise</li>

 <li>@('(IF x y z)') &mdash; @('y') if @('x') is non-@('NIL') and @('z') if
 @('x') is @('NIL').  Put more colloquially, @('(IF x y z)') means &ldquo;if
 @('x') is true, return @('y'), otherwise return @('z')&rdquo;</li>

 <li>@('(COND (p1 x1) (p2 x2) ... (T xn))') &mdash; an abbreviation for
 <code>
 (IF p1
     x1
     (IF p2
         x2
         (IF ...
             ...
             y)))
 </code></li>

 <li> @('(AND x1 ... xn)') &mdash; @('xn') if each @('xi') is non-@('nil'),
 and @('nil') otherwise </li>

 <li> @('(OR x1 ... xn)') &mdash; @('xi') for the first @('xi') that is
 non-@('nil'), @('nil') otherwise </li>

 <li> @('(NOT x)') &mdash; @('t') if @('x') is @('nil') and @('nil') otherwise </li>

 <li> @('(NATP x)') &mdash; @('t') if @('x') is a non-negative integer and @('nil') otherwise </li>

 <li> @('(INTEGERP x)') &mdash; @('t') if @('x') is an integer and @('nil') otherwise </li>

 <li> @('(RATIONALP x)') &mdash; @('t') if @('x') is a rational number and @('nil') otherwise </li>

 <li> @('(ZP x)') &mdash; @('nil') if @('x') is a positive integer and @('t') otherwise </li>

 <li> @('(+ x1 ... xn)') &mdash; sum of the @('xi') </li>

 <li> @('(* x1 ... xn)') &mdash; product of the @('xi') </li>

 <li> @('(- x y)') &mdash; @('x') minus @('y') </li>

 <li> @('(/ x y)') &mdash; quotient of @('x') divided by @('y') </li>

 <li> @('(< x y)') &mdash; @('t') if @('x') is less than @('y') and @('nil')
 otherwise </li>

 <li> @('(<= x y)') &mdash; @('t') if @('x') is less than or equal to @('y')
 and @('nil') otherwise </li>

 <li>@('(CONSP x)') &mdash; @('t') if @('x') is a cons pair and @('nil') otherwise </li>

 <li>@('(ATOM x)') &mdash; @('t') if @('x') is a not cons pair and @('nil') otherwise </li>

 <li>@('(ENDP x)') &mdash; @('t') if @('x') is @('nil') or a not cons pair and @('nil') otherwise </li>

 <li> @('(CONS x y)') &mdash; the ordered pair whose left-hand component is @('x') and whose right-hand component is @('y') </li>

 <li> @('(CAR x)') &mdash; left-hand component of @('x') if @('x') is a cons pair and @('nil') otherwise  </li>

 <li> @('(CDR x)') &mdash; right-hand component of @('x') if @('x') is a cons pair and @('nil') otherwise  </li>

 <li> @('(CADR x)') &mdash; @('(CAR (CDR X))') </li>

 <li> @('(CDDR x)') &mdash; @('(CDR (CDR X))') </li>

 <li> @('(LIST x1 x2 ... xn)') &mdash; @('(CONS x1 (CONS x2 ... (CONS xn NIL)))') </li>

 <li> @('(LIST* x1 x2 ... xn)') &mdash; @('(CONS x1 (CONS x2 ... xn))') </li>

 <li> @('(SYMBOLP x)') &mdash; @('t') if @('x') is a symbol and @('nil') otherwise </li>

 <li> @('(STRINGP x)') &mdash; @('t') if @('x') is a string and @('nil') otherwise </li>

 <li> @('(CHARACTERP x)') &mdash; @('t') if @('x') is a character and @('nil') otherwise </li>

 </ul>

 <p>You can learn more about these functions by executing them on some sample
 data.  For example, the value of @('(AND T 23 33)') is @('33'), @('(+ 1 2 3)')
 is @('6'), @('(ZP 0)') is @('T') but @('(ZP 3)') is false (i.e., @('NIL')).
 @('(LIST 1 (+ 2 2) (+ 3 3))') has the value @('(1 4 6)') but @('(LIST* 1 (+ 2
 2) (+ 3 3))') has the value @('(1 4 . 6)').</p>

 <p>Perhaps more interestingly, the value of @('(EQUAL (CONS (- 6 1) 7) (CONS
 5 (+ 5 2)))') is @('T').  &ldquo;Behind the scenes&rdquo; those two calls of
 @('CONS') return two different pointers to two different newly allocated
 regions of memory, but the <i>car</i> and <i>cdr</i> fields of both objects
 are the same, namely @('5') and @('7') respectively.  ACL2 cannot tell those
 two pointers apart.  Operationally, @('EQUAL') checks equality recursively
 down to the tips of both objects.  But logically, both @('CONS') expressions
 here return the pair @('(5 . 7)').</p>

 <h2>Common Patterns of Recursion</h2>

 <p>
 Most of your function definitions in ACL2 will fall into certain common
 schemes.  Here is an informal description of the three most common
 schemes.  We define the function @('visit') several different
 ways to illustrate common recursions.  (In ACL2 you are not allowed to
 define a function more than one way; there is no &ldquo;overriding,&rdquo; &ldquo;hiding,&rdquo;
 or &ldquo;overloading.&rdquo;  These multiple definitions are just a device for
 illustrating a lot of definitions without burdening you with many different
 names.)</p>

 <h3>Visiting every element of a linear list</h3>

 <code>
 (defun visit (lst ...)
   (cond ((endp lst) ...)              ; <i>No elements left to process.</i>
         (t .                          ; <i>Some elements to process:</i>
             .
              .
               (car lst)               ; <i>do something with this element</i>

               (visit (cdr lst) ...)   ; <i>and visit the rest.</i>
              .
             .
            .)))
 </code>
 <p>
 We illustrate this scheme in the next section.</p>

 <h3>Visiting every node and leaf in a binary tree</h3>

 <code>
 (defun visit (tree ...)
   (cond ((atom tree) ...)             ; <i>The tree is a leaf: do something.</i>

         (t .                          ; <i>The tree is an interior node:</i>
             . tree                    ; <i>do something with it,</i>
              .
                (visit (car tree) ...) ; <i> visit nodes in left branch, and</i>

              . (visit (cdr tree) ...) ; <i> visit nodes in right branch.</i>
             .
            .)))
 </code>

 <p>
 Visiting every element of a linear list is just the
 special case of exploring a binary tree in which we visit only the successive
 subtrees along the @('cdr') chain and consider the @('car')
 of each such subtree as the &ldquo;data,&rdquo; or element, to be processed.
 We illustrate this recursion below.</p>

 <h3>Visiting all the natural numbers from n to 0</h3>

 <code>
 (defun visit (n ...)
   (cond ((zp n) ...)                  ; <i>N &ldquo;is&rdquo; 0: finish up!</i>
         (t .                          ; <i>N is a positive integer:</i>
             . n                       ; <i>do something with it, and</i>
              .
               (visit (- n 1) ...)     ; <i>visit the naturals below it.</i>
              .
             .
            .)))
 </code>
 <p>
 The reason &ldquo;is&rdquo; is in quotation marks above is that @('(zp n)') is
 true if either @('n') is 0 or @('n') is not a natural number.
 For example, @('(zp -3)') and @('(zp 1/3)') both return true!
 So when @('(zp n)') is true you don't <i>really</i> know
 @('n') is 0 but you do know there is nothing more to do,
 if you're thinking of @('n') as a natural number.  When
 @('(zp n)') is false, you <i>know</i> @('n') is a positive
 integer.  The predicate @('zp') is just a convenient way to recur
 through natural numbers and guarantees to halt the recursion even if you call
 the function on &ldquo;unexpected&rdquo; input, whether numeric or not.</p>

 <h2>Computing Results</h2>

 <p>
 When you define a recursive function you often have the choice of computing
 the results &ldquo;on the way up&rdquo; or &ldquo;on the way down.&rdquo;</p>

 <p>
 Suppose @('x') is a linear list of numbers and you wish to sum them.
 Here are two ways:</p>
 <code>
 (defun sum-up (x)
   (cond ((endp x) 0)
         (t (+ (car x) (sum-up (cdr x))))))

 (defun sum-down (x temp)
   (cond ((endp x) temp)
         (t (sum-down (cdr x) (+ (car x) temp)))))
 </code>
 <p>
 For example @('(sum-up '(1 2 3 4))') is @('10') and
 @('(sum-down '(1 2 3 4) 7)') is @('17').
 Both definitions fit within the &ldquo;visiting every element of a
 linear list&rdquo; recurrence scheme.</p>

 <p>
 Note that @('sum-up') takes a list of numbers and returns their sum
 while @('sum-down') takes a list of numbers and some initial value
 and adds the numbers in the list to the initial value.  Of course,
 @('(sum-up x)') is equal to @('(sum-down x 0)') &mdash;
 but only because the operation of addition is insensitive to the order
 in which the additions are done.</p>

 <p>
 In many applications, the @('sum-up') style is clearer, as it is
 obvious how each element of the list is contributing to the final value.  In
 particular, each element is handled in exactly the same way regardless of
 what elements came before.  In the @('sum-down') style, the value of
 the temporary variable can, in principle, be used to affect the processing of
 subsequent elements.  Information about the previous elements is being passed
 down.  In more complicated functions written in the @('sum-down')
 style, one must carefully inspect how @('temp') is used to determine
 if it is just the final answer or is being used to direct the computation.</p>

 <p> Of course, sometimes information about the elements already visited is
 necessary to decide how to process subsequent ones, in which case the
 @('sum-down') style might be the appropriate choice.</p>

 <p> Finally, when these two functions are compiled in a straightforward way,
 the recursion in @(' sum-up') may a call stack while the recursion in @('
 sum-down') does not: @('sum-down') is <i>tail recursive</i>.  This means that
 the value of the recursive call is returned as the final answer and there is
 no need for the execution engine to &ldquo;remember&rdquo; to come back after
 the call to &ldquo;do something.&rdquo; In @('sum-up') the execution engine
 must &ldquo;remember&rdquo; to add the two intermediate results together.
 Tail recursive calls can be compiled as simple jumps or &ldquo;gotos&rdquo;
 and often result in faster executions and use of no additional stack space.
 But all such considerations depend critically on the sophistication of the
 compiler.</p>

 <h2>Saving Intermediate Results</h2>

 <p>
 ACL2 is applicative so it does not have assignment statements.  But it is
 possible to use &ldquo;local variables&rdquo; to save intermediate results.
 Here is a function that computes x^4 + y^4, i.e., the sum of the fourth
 powers of @('x') and @('y').</p>

 <code>
 (defun x4y4 (x y)
   (let ((x2 (* x x))            ; Let x2 be x^2 and, &ldquo;simultaneously,&rdquo;
         (y2 (* y y)))           ; let y2 be y^2.
     (+ (* x2 x2)                ; Compute x^4 by squaring x^2 and
        (* y2 y2))))             ; add it to y^4 computed similarly.
 </code>

 <p> For example, @('(x4y4 2 3)') is @('16') + @('81') or @('97').  The
 @('let') expression has two parts, a list of variable bindings followed by a body.
 The bindings are written as a list of elements.  Each element lists a variable
 name and a term.  The terms are evaluated in parallel and then all the
 variables are bound to the values of the corresponding terms.  Then the body
 is evaluated.  The value of the body is the value of the @('let').</p>

 <p>@('Let') expressions are formalized in ACL2 as applications of anonymous
 functions.  For example, @('(let ((v1 a1) (v2 a2)) (g v1 v2))') is actually
 transformed into @('((lambda (v1 v2) (g v1 v2)) a1 a2)') where the @('lambda')
 expression is an anonymous function with two parameters, @('v1') and @('v2'),
 and body @('(g v1 v2)').  The terms @('a1') and @('a2') that determine the
 values of the local variables in the @('let') become the argument expressions
 on which the anonymous function is called.</p>

 <p>
 While @('let') binds its variables in parallel, @('let*')
 binds its variables sequentially.  The expression</p>
 <code>
 (let* ((x2 (* x x))             ; Let x2 be x^2, and then
        (x4 (* x2 x2))           ; let x4 be x2^2, and then
        (x8 (* x4 x4)))          ; let x8 be x4^2.
       x8)                       ; Return x8.
 </code>
 <p>
 computes @('x')^8.</p>

 <p>
 Here is an example of a common use of @('let').  Suppose you wish
 to find the length of the longest branches in a binary tree.  The function
 @('depth') does that.  It is an example of the &ldquo;visit every node
 in a binary tree&rdquo; scheme.</p>
 <code>
 (defun depth (x)
   (cond ((atom x) 0)
         (t (let ((left-depth (depth (car x)))
                  (right-depth (depth (cdr x))))
               (if (&lt; left-depth right-depth)
                   (+ 1 right-depth)
                   (+ 1 left-depth))))))
 </code>

 <p>
 Just to illustrate the definition and list notation, consider the
 tree</p>
 <code>
           *
          / \
         /   \
        *     *
       / \   / \
      a   * e   *
         / \   / \
        b   * f   g
           / \
          c   d
 </code>
 <p>
 The longest branches in this tree have length four and terminate in either
 @('c') or @('d').  This tree can be written</p>
 <code>
 ((a . (b . (c . d))) . (e . (f . g)))
 </code>
 <p>
 or equivalently as @('((a b c . d) e f . g)').</p>

 <p>
 The expression @('(depth '((a b c . d) e f . g))') has value 4.</p>

 <p>
 We could have defined this function this way:</p>
 <code>
 (defun depth (x)
   (cond ((atom x) 0)
         (t (if (&lt; (depth (car x))
                   (depth (cdr x)))
                (+ 1 (depth (cdr x)))
                (+ 1 (depth (car x)))))))
 </code>
 <p>
 But this would execute less efficiently because after recurring into both the
 car and cdr of @('x') to determine which is deepest it recurs into
 one of them again to return the answer.  The use of @('let')
 eliminates this duplication of effort by saving the results of the earlier
 calls.</p>

 <p>
 Still a third way to define @('depth') might be</p>
 <code>
 (defun depth (x)
   (cond ((atom x) 0)
         (t (+ 1 (max (depth (car x))
                      (depth (cdr x)))))))
 </code>
 <p>
 where @('(max i j)') is defined to be @('(if (&lt; i j) j
 i)').  This definition executes almost as efficiently as the first
 one.  The values of the two recursive calls are passed to the subroutine
 @('max').  @('Max') uses @('i') twice and
 @('j') twice but now that &ldquo;duplication of effort&rdquo; only requires
 looking up the values of variables, just as in the @('let') case.</p>

 <h2>Sample Definitions</h2>

 <h1>Functions on Linear Lists</h1>

 <p>
 The next several functions all illustrate the &ldquo;visiting every element of
 a linear list&rdquo; recurrence scheme.</p>

 <code>
 (defun mem (e x)

 ; Return t or nil according to whether e is an element of x.

   (cond ((endp x) nil)
         ((equal e (car x)) t)
         (t (mem e (cdr x)))))
 </code>

 <p>
 Equivalently:</p>
 <code>
 (defun mem (e x)
   (if (endp x)
       nil
       (if (equal e (car x))
           t
           (mem e (cdr x)))))
 </code>
 <p>
 or even</p>
 <code>
 (defun mem (e x)
   (and (not (endp x))
        (or (equal e (car x))
            (mem e (cdr x)))))
 </code>
 <p>
 (Recall our caveat about multiple definitions of the same function.  If you
 want to try one of these definitions in ACL2, fine.  If you want to try all
 three, you'll have to give them distinct names.)</p>

 <p>
 For all three of the above definitions, the following examples hold:</p>
 <code>
 ACL2 p!&gt;(mem 'd '(a b c d e f g))
 T
 ACL2 p!&gt;(mem 'd '(a b c   e f g))
 NIL
 ACL2 p!&gt;
 </code>

 <p>
 Here is a function to concatenate two lists together:</p>
 <code>
 (defun app (x y)
   (if (endp x)       ;;; If x is exhausted,
       y              ;;;    then return y
       (cons (car x)  ;;;  else, cons the first element of x onto
             (app     ;;;     the list obtained by recursively appending
              (cdr x) ;;;     the rest of x
              y))))   ;;;     to y.
 </code>

 <p>Here are some examples of @('app').</p>

 <code>
 ACL2 p!&gt;(app '(1 2 3) '(a b c d))
 (1 2 3 A B C D)
 ACL2 p!&gt;(app '(1 2 3) nil)
 (1 2 3)
 ACL2 p!&gt;(app (app '(1 2 3) '(4 5 6)) '(7 8 9))
 (1 2 3 4 5 6 7 8 9)
 ACL2 p!&gt;
 </code>

 <p>
 Here is a function to find the first pair in an alist (if any) that binds a given
 key.</p>
 <code>
 (defun lookup (key alist)
   (cond ((endp alist) nil)             ;;; If alist empty, return nil,
         ((equal key (car (car alist))) ;;; elseif the first pair contains key,
          (car alist))                  ;;;    then return the first pair,
         (t (lookup key (cdr alist))))) ;;; else look in the rest of alist.
 </code>

 <p>Here are some examples.</p>

 <code>
 ACL2 p!&gt;(lookup 'b '((a . 1)(b . 2) (c . 3)))
 (B . 2)
 ACL2 p!&gt;(lookup 'd '((a . 1)(b . 2) (c . 3)))
 NIL
 ACL2 p!&gt;(lookup 'b '((a . 1)(b . 2) (b . 3)))
 (B . 2)
 ACL2 p!&gt;
 </code>

 <p>Note that only the first binding of the key matters.</p>

 <p>
 Here is a function to &ldquo;change&rdquo; the value of a key in an alist.  Note
 that it does not modify the alist but produces a new alist.</p>
 <code>
 (defun store (key val alist)
   (cond
     ((endp alist)                 ;;; If alist is empty,
      (list (cons key val)))       ;;;  then return an alist with one binding,
     ((equal key (caar alist))     ;;; elseif the first pair binds key,
      (cons (cons key val)         ;;;  then add the new binding to
            (cdr alist)))          ;;;  the rest of the alist,
     (t (cons (car alist)          ;;; else cons this pair onto the result
              (store               ;;;  of recursively putting a new binding
                key val            ;;;  of key to val in
                (cdr alist))))))   ;;;  the rest of alist.
 </code>

 <code>
 ACL2 p!&gt;(store 'b 7 '((a . 1) (b . 2) (c . 3)))
 ((A . 1) (B . 7) (C . 3))
 ACL2 p!&gt;(store 'x 26 '((a . 1) (b . 2)))
 ((A . 1) (B . 2) (X . 26))
 ACL2 p!&gt;(store 'c 3 '((a . 1) (b . 2) (x . 26)))
 ((A . 1) (B . 2) (X . 26) (C . 3))
 </code>

 <p>
 It is important to recall that ACL2 is functional (side-effect free)!
 Despite its name, @('store') does not change the alist it is given
 but returns a new one.  Consider</p>
 <code>
 ACL2 p!&gt;(let* ((alist1 '((a . 1) (b . 2) (c . 3)))
                (alist2 (store 'b 7 alist1)))
          (list (lookup 'b alist1)
                (lookup 'b alist2)))
 ((B . 2) (B . 7))
 ACL2 p!&gt;
 </code>

 <p> The above expression binds @('alist1') to an alist in which @('b') is
 associated with 2.  Then it uses @('store') to bind @('b') in @('alist1') to
 the new value @('7') and calls the result @('alist2').  Then it returns the
 list containing the values of looking up @('b') in each of the alists.
 You might think the answer would be @('((B . 7) (B . 7))') and it <i>would be
 if</i> @('store') actually changed @('alist1') to create @('alist2').  But in
 fact @('alist1') is not changed.  The answer is @('((B . 2) (B . 7))').</p>

 <h1>Functions on Binary Trees</h1>

 <p>
 Here is a function to count the number of tips of a binary tree.  This function
 illustrates the &ldquo;visiting every node of a binary tree&rdquo; scheme.</p>
 <code>
 (defun count-tips (x)
   (cond ((atom x) 1)                   ;;; X is a tip: it counts 1.
         (t (+ (count-tips (car x))     ;;; X is a node: sum the counts
               (count-tips (cdr x)))))) ;;; of the left and right subtrees.
 </code>
 <p>
 The function above does the computation &ldquo;on the way up.&rdquo;</p>

 <p>
 Here is a version that does it &ldquo;on the way down.&rdquo;</p>
 <code>
 (defun count-tips (x temp)
   (cond ((atom x) (+ 1 temp))          ;;; X is a tip: add its count to temp.
         (t                             ;;; Otherwise, x is a node:  Read the
                                        ;;; nest of two calls below inside-out:
                                        ;;; Count the tips in (car x) and add
                                        ;;; that into temp.  Use the result as
                                        ;;; temp when you count the tips in
                                        ;;; (cdr x).
          (count-tips (cdr x)
                      (count-tips (car x)
                                  temp)))))
 </code>
 <p>
 This function has one tail recursive call.</p>

 <p>
 Let @('x') be the tree</p>
 <code>
           *
          / \
         /   \
        *     *
       / \   / \
      a   * e   *
         / \   / \
        b   * f   g
           / \
          c   d
 </code>
 <p>
 which we can write as @(''((a b c . d) e f . g)').  Then
 @('(count-tips x)') is @('7') (here we mean to use
 the first version of the definition).  Similarly,
 @('(count-tips x 0)') is also @('7') (here we mean
 to use the second version).</p>

 <h2>Mutual Recursion</h2>

 <p>
 ACL2 requires that subroutines be defined before they are used in other
 definitions.  So what do you do if you have two functions, <i>f</i> and
 <i>g</i>, and <i>f</i> calls <i>g</i> and <i>g</i> calls <i>f</i>?
 You define them together.
 This is called <i>mutual recursion</i>.</p>

 <p>
 The example below shows a very inefficient way to factor a number into a list
 of primes.</p>
 <code>
 (mutual-recursion

 (defun factors (n)

 ; Collect the prime factors of n.

   (factors-below n (- n 1)))

 (defun factors-below (n m)

 ; Return the prime factors of n that are less than or equal to m.

   (cond ((or (zp m)
              (equal m 1))
          (list n))
         ((integerp (/ n m))
          (app (factors (/ n m))
               (factors m)))
         (t (factors-below n (- m 1)))))
 )
 </code>
 <p>
 We can read this as follows.  To determine the @('factors') of
 <i>n</i>, call @('factors-below') on <i>n</i> and <i>n-1</i> to
 collect all the factors of <i>n</i> less than or equal to <i>n-1</i>.  To
 find all the factors of <i>n</i> less than or equal to <i>m</i>, consider
 three cases.  First, if <i>m</i> is 0 or 1, return the list containing just
 <i>n</i>.  Second, if <i>n/m</i> is an integer (i.e., <i>m</i> divides
 <i>n</i>), then use @('app') to concatenate the factors of
 <i>n/m</i> to the factors of <i>m</i>.  Third (and otherwise), find the
 factors of <i>n</i> below <i>m-1</i>.</p>

 <p>We can run @('factors').  For example @('(factors 12)') returns @('(2 2
 3)').  If we call @('(factors 123456789)') the computation takes a while (27
 seconds on my laptop) and returns @('(3 3 3607 3803)').  @('(Factors (- (expt
 2 31) 1))') takes about 500 seconds and returns @('(2147483647)').</p>

 <h2>Returning and Using Multiple Values</h2>

 <p>It is sometimes useful to define functions that return more than one
 result.  Here is an example of a function that produces and uses multiple
 values.  The function explores a binary tree and counts (in its second
 argument, @('nodes')) how many cons nodes it sees and counts (in its third
 argument, @('tips')) how many tips it sees.  It returns both numbers as a list
 of length 2 (without actually creating the intermediate lists).</p>

 <code>
 (defun node-and-tip-count (x nodes tips)
   (cond
    ((atom x)                ;;; X is a tip.  Return a vector (list) of
     (mv nodes               ;;; two results: the number of nodes seen
         (+ 1 tips))         ;;; and the number of tips seen (plus 1 for x).
     )
    (t                       ;;; X is a cons node.

       (mv-let (nodes-in-car tips-in-car)
               (node-and-tip-count (car x) nodes tips)

               ;;; The two lines above locally bind the variables
               ;;; nodes-in-car and tips-in-car to the number of
               ;;; nodes and tips, respectively, computed by the
               ;;; recursive call of this function on (car x)
               ;;; and the current running counts of nodes and tips.

               ;;; Then, below, we count the number of nodes and
               ;;; tips in (cdr x), starting with the counts for
               ;;; the car (and adding one for the node x).

               (node-and-tip-count (cdr x)
                                   (+ 1 nodes-in-car)
                                   tips-in-car)))))
 </code>

 <p>
 For example,</p>
 <code>
 (node-and-tip-count '((a . b) . (c . d)) 0 0)
 = (3 4)
 </code>

 <p>Thus, the tree in question has 3 cons nodes and 4 (non-cons) tips.</p>

 <p>If you want to use multiple values you should read the ACL2 documentation
 on that topic.</p>

 <h2>Type Errors</h2>

 <p>The ACL2 programming language is untyped.  Objects have types that can be
 checked at runtime with predicates like @('integerp'), @('consp'), etc., but
 there is no syntactic typing.  Any function can be applied to any object and
 ACL2 comes up with some value.  It does this by defaulting ill-typed inputs to
 default values of the expected type.  For example, @('+') expects its
 arguments to be numbers.  If you supply a non-numeric input to @('+') it will
 use @('0') instead.  Thus, the value of @('(+ 3 T)') is @('3').  @('Car') and
 @('cdr') expect their arguments to be either a cons pair or @('nil').  (A
 special case in Lisp is that @('car') and @('cdr') return @('nil') on
 @('nil').)  If called on objects of the wrong type, @('car') and @('cdr')
 default the argument to @('nil').</p>

 <p>But when you start up ACL2, the read-eval-print loop is configured to
 check types as it evaluates.  Errors are signaled if types are violated.
 However, if you want it to just plow into ill-typed data and get whatever
 result the defaults produce, you can use the @(':set-guard-checking nil')
 command as shown in the session below.</p>

 <code>
 ACL2 p!&gt;(+ 2 2)
 4
 ACL2 p!&gt;(+ 2 T)


 ACL2 Error in TOP-LEVEL:  The guard for the function call (BINARY-+ X Y),
 which is (AND (ACL2-NUMBERP X) (ACL2-NUMBERP Y)), is violated by the
 arguments in the call (BINARY-+ 2 T).
 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!&gt;: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 p&gt;(+ 2 T)
 2
 ACL2 p&gt;(CAR 'ABC)
 NIL
 ACL2 p&gt;
 </code>

 <p>Note that the prompt changes after the @(':set-guard-checking') command
 above.  The exclamation mark (@('!')) in the standard prompt indicates that
 types are being checked.</p>

 <h2>Stack Overflow</h2>

 <p>Sometimes a computation will consume more space than your machine has.
 For example, the following function constructs a list of @('n') @('nil')s.</p>

 <code>
 (defun nils (n)
   (if (zp n)
       nil
       (cons nil (nils (- n 1)))))
 </code>

 <p>We can run it on small values of @('n').</p>

 <code>
 (nils 10) = (nil nil nil nil nil nil nil nil nil nil)
 </code>

 <p>So that we don't have to read long lists of @('nil')s below we just take
 the length of the result with the ACL2 function @('len').</p>

 <code>
 ACL2 p!&gt;(len (nils 10))
 10
 ACL2 p!&gt;(len (nils 100))
 100
 ACL2 p!&gt;(len (nils 1000))
 1000
 ACL2 p!&gt;(len (nils 10000))
 10000
 ACL2 p!&gt;(len (nils 100000))
 100000
 ACL2 p!&gt;(len (nils 1000000))
 1000000
 ACL2 p!&gt;(len (nils 10000000))
 ***********************************************
 ************ ABORTING from raw Lisp ***********
 ********** (see :DOC raw-lisp-error) **********
 Error:  Stack overflow on value stack.
 ...
 :q
 ACL2 p!&gt;
</code>

 <p>But that last test, where we attempt to produce a list of ten million
 @('nil')s, causes a stack overflow in the Common Lisp configuration I'm
 running.  (If your Lisp causes a Lisp error and enters an interactive break
 you'll need to exit the break to return to ACL2.  Exactly how you do that
 depends on what Common Lisp you're running.  For example, in GCL and CCL, you
 type @(':q') followed by return, but in Allegro CL you type @(':reset')
 followed by return, and in CMU CL you type @('q') followed by return.)</p>

 <p>If you are interested in doing ``large'' calculations with ACL2 you will have
 to learn about how to compile definitions and how to use declarations to optimize
 code.  Those topics are beyond the scope of this document.</p>

 <p>However, often you can just code up a more efficient algorithm.  For
 example, the following tail-recursive version of @('nils') won't overflow the stack.</p>

 <code>
 (defun nils (n ans)
   (if (zp n)
       ans
       (nils (- n 1) (cons nil ans))))
 </code>

 <p>So now</p>

 <code>
 ACL2 p!&gt;(len (nils 10000000 nil))
 10000000
 ACL2 p!&gt;(len (nils 100000000 nil))
 100000000
 ACL2 p!&gt;(len (nils 1000000000 nil))
 1000000000
 ACL2 p!&gt;
 </code>

 <p>Of course, it will eventually use up all the memory.</p>

 <p>The tests above sort of suggest we're interested in the question &ldquo;Does @('(nils n nil)') always return a
 list of length @('n')?&rdquo;  If that is the question, then (a) you'll never answer it by running all possible
 tests, and (b) you are using exactly the right tool!</p>

 <p>The ACL2 system includes a theorem prover.  Below we show the commands you
 need to execute to answer the question in the affirmative.  We've elided the
 output from these commands.</p>

 <code>
 ACL2 p!&gt;:logic
 ACL2 !&gt;(verify-termination nils)
 ...
 ACL2 !&gt;(defthm lemma-about-nils
         (implies (natp n)
                  (equal (len (nils n ans))
                         (+ n (len ans)))))
 ...
 ACL2 !&gt;(defthm main-theorem-about-nils
         (implies (natp n)
                  (equal (len (nils n nil)) n)))
 ...
 </code>

 <p>That is, switch back into logic mode, admit @('nils') to the logic by
 proving termination, prove the general theorem that @('(nils n ans)') returns
 a list whose length is @('n') plus the length of @('ans'), when @('n') is
 natural number, and then prove the main theorem.  Your job as an ACL2
 &ldquo;theorem prover driver&rdquo; is to think of the commands.  The prover
 does the work to complete each of those steps.</p>

 <p>So maybe you should learn to prove theorems about your functions?  If so,
 see &ldquo;Recursion and Induction&rdquo;.</p>

 <h2>Conclusion</h2>

 <p>You should be ready at this point to use ACL2 as a programming language to
 implement lots of simple list processing algorithms.  Remember to go to the
 ACL2 User's Manual on the <a
 href='https://www.cs.utexas.edu/users/moore/acl2'>ACL2 Home Page</a> to learn
 about other functions and features.  If you need advice, check out the ACL2
 Help list under the Mailing Lists link.  The users who have volunteered to
 help are very responsive.</p>

 <p>One final piece of advice: it is always best to code the simplest algorithm
 you can.  Do not needlessly complicate your code.  Optimize for performance
 only after confirming that the straightforward implementation is too
 inefficient for your application.</p>

 ")
other
(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>")
other
(defxdoc get-cpu-time
  :parents (programming-with-state acl2-built-ins read-run-time)
  :short "Read elapsed cpu time"
  :long "<p>@('(Get-cpu-time state)') returns the elapsed cpu time in seconds
 since the start of the current ACL2 session.  See @(see read-run-time) for
 further documentation.</p>

 @(def get-cpu-time)")
other
(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>")
other
(defxdoc get-event-data
  :parents (system-utilities output-controls)
  :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, which we call an <i>event-data alist</i>.
 Such an alist is the value of @(see state) global variable
 @('last-event-data').  (See @(see programming-with-state) for a discussion of
 state global variables.)  An event-data alist contains certain information
 stored at the conclusion of the immediately preceding event, some of which
 corresponds to the event's @(see summary).  We anticipate continuing to
 support at least the following keys, each with value @('VAL') 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>@('EVENT'): the @(see event).</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.  Note: This value can be obtained using @(tsee
 last-prover-steps).</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>@('SYSTEM-ATTACHMENTS'): @('VAL') lists the pairs @('(f . g)') for which
 @('f') is a system function with attachment @('g') (@(see defattach)), which
 differs from the attachment to @('f') when ACL2 starts up.</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>")
other
(defxdoc get-guard-checking
  :parents (redundant-events)
  :short "Get the status most recently installed by @(tsee set-guard-checking)"
  :long "<p>See @(see set-guard-checking) for relevant background.  The value
 returned by @('(get-guard-checking)') is @('t') by default, but is the value
 most recently installed for @(see guard)-checking, typically supplied as the
 argument of a call of @(tsee set-guard-checking).</p>")
other
(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.
 These are most visibly used in reporting the time summaries when completing
 evaluation of @(see events).  For utilities that return elapsed cpu or run
 time, see @(see read-run-time), @(see get-cpu-time), and @(see get-real-time).
 Other time-related utilities include @(see with-prover-time-limit), @(see
 time-tracker), @(see time-tracker-tau), 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
 functions @('get-internal-run-time') for cpu time (or a slight variant if the
 host Lisp is a version of GCL that precedes 2.7.0) and
 @('get-internal-real-time') for real (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 @(see summary) might be as follows, drastically
 under-reporting the actual elapsed (real, wall clock) 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), and also see @(see get-cpu-time) and
 @(see get-real-time).</p>")
other
(defxdoc get-persistent-whs
  :parents (wormhole)
  :short "Make a wormhole's status visible outside the wormhole"
  :long "@({
  General Form:
  (get-persistent-whs name state)
  })

 <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 persistent-whs of the named wormhole (i.e., the status of
 of wormhole stored outside of the ACL2 state).  The status is obtained by
 reading the oracle in the ACL2 @(tsee state) with @(tsee
 read-acl2-oracle).</p>

 <p>Recall that the status of a wormhole is some ACL2 object largely determined
 by the author of the wormhole.  It is always treated as a pair whose @('car')
 is the &ldquo;entry code&rdquo; (@(':enter') or @(':skip')) or, more
 precisely, is either @(':skip') or not @(':skip'), the latter case being
 treated like @(':enter').  But the @('cdr') of the status can be whatever the
 author of the wormhole chooses to hold the data of the wormhole.  When a
 wormhole is entered its persistent status, aka its persistent-whs, is used to
 configure the state of the read-eval-print loop the user sees inside the
 wormhole.  In particular, upon entry the persistent-whs is moved to the value
 of the state global variable @(''wormhole-status') and is thus accessible via
 @('(f-get-global 'wormhole-status state)').  We call this copy of the status
 the ephemeral-whs because when the wormhole is exited the ephemeral-whs is
 moved to the @('persistent-whs') and the state global @(''wormhole-status')
 is restored to whatever value it had when the wormhole was entered.</p>

 <p>See @(tsee wormhole-status) for a discussion of these two senses of the
 status of a wormhole.  See also @(see wormhole-programming-tips).</p>")
other
(defxdoc get-real-time
  :parents (programming-with-state acl2-built-ins read-run-time)
  :short "Read elapsed real time"
  :long "<p>@('(Get-real-time state)') returns @('(mv rtime state)') where
  @('rtime') is the elapsed real (wall clock) time in seconds since the start
  of the current ACL2 session.  See @(see read-run-time) for further
  documentation.</p>

 @(def get-real-time)")
other
(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$)")
other
(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)")
other
(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)")
other
(defxdoc git-quick-start
  :parents (about-acl2)
  :short "Git quick start guide."
  :long "<p>The
 <a href='https://github.com/acl2/acl2'>ACL2 GitHub repository</a>
 contains the ``bleeding edge'' ACL2 source code and @(see community-books),
 available between ACL2 <see topic="ACL2____RELEASE-NOTES">releases</see>.</p>

 <p>Here we provide minimal instructions for working with the ACL2 GitHub
 repo.  Many git tutorials are available elsewhere on the web (e.g., <a
 href='https://docs.github.com/en/get-started'>at GitHub</a>).</p>

 <h2>For non-contributors (to use ACL2 without contributing changes):</h2>

 <p>Start by obtaining the ACL2 GitHub repository (this command makes a
 directory called @('acl2') that contains the current contents of the
 @('master') branch):</p>

 @({
 git clone https://github.com/acl2/acl2
 })

 <p>Later, to update your copy to get the latest changes:</p>

 @({
 cd acl2
 git pull
 })

 <p>Once you have ACL2, you will probably want to certify some books (see
 @(see books-certification)).</p>

 <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).")
other
(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 for contributors who commit to the repository
  often (e.g., monthly or weekly).  Such contributors will typically
  begin with the @(see github-commit-code-using-pull-requests) method, and
  after they are familiar with the process and community, will switch to
  this method.</p>

 <p> If you do not plan to commit your own changes, see @(see git-quick-start)
 instead.</p>

 <h2>(A) GETTING STARTED</h2>

 <p>Start by obtaining an up-to-date copy of the web-based GitHub
 repository (this command makes a directory called @('acl2') that contains the
 current contents of the @('master') branch).</p>

 @({
 git clone https://github.com/acl2/acl2
 cd acl2
 })

 <h2>(B) UPDATING</h2>

 <p>The following commands will update your directory to match the latest
 contents of the main ACL2 repository on GitHub.</p>

 @({
 git fetch --all
 git merge -m "Merge." remotes/origin/master
 })

 <h2>(C) CONTRIBUTING</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>Eric Smith (@('eric.smith@kestrel.edu'))</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>Make Changes and Test Them</h3>

 <ol>

 <li>Before beginning your edits, update, as in (B) above.</li>

 <li>Build an executable.

 @({
 make update LISP=<your_lisp>
 })</li>

 <li>Make book changes.  See the guidelines in the @(see how-to-contribute) topic
  (e.g., about updating the book release notes).</li>

 <li>Run a regression.

 @({
 (make -j 8 regression) >& 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 3 above to make appropriate
 changes and re-test.</li>

 <li>Commit your changes.  First do @('git status') to see the list of all
 new/changed files:

 @({
 git status
 })

 Ensure that none of the reported additions/changes was unintentional.  Next,
 do @('git add') to add each file you want to commit (normally, everything
 reported by @('git status'), to match what was tested in the regression above):

 @({
 git add <file1> <file2> ...
 })

 Now commit your changes locally:

 @({
 git commit -m '<some message, with descriptive first line>'
 })

 The @('-m ...')  option is a log message, where the first line is a summary
 of your changes and additional lines give more details.  You can replace
 the @('-m ...') option by @('-F <filename>'), where @('<filename>') is the
 name of a file that contains your log message.</li>

 <li>Merge in remote changes, if any, by updating again as in (B) above.

 If the merge changed anything, go back to Step 4 above to ensure that your
 changes are compatible with the remote changes you just obtained.  If the
 merge did not change anything, continue to the next step (Contribute Your
 Changes).

 In rare cases, you may get a merge conflict (concurrent changes to the same
 files), in which case you will need to resolve the conflict by editing files
 and committing them (see the @('git commit') command above in Step 7).  Then
 go back to Step 4 above to test that everything is working.

 </li>

 </ol>

 <h3>Contribute Your Changes</h3>

 <p>The following command will update the main ACL2 repository on GitHub.</p>

 @({
  git push origin testing
 })

 <p>This will cause your changes to be merged into the @('testing') branch.
 From there, they will be automatically merged into @('master') if the automated
 regression testing system successfully tests them.</p>

 <p>Note: If you are changing someone else's files, or would like someone to
 review your changes, you might consider making a pull request instead of
 pushing directly.</p>")
other
(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 for contributors who will commit to the repository
  rarely (e.g., a few times a year). If you find yourself committing more often,
  see @(see github-commit-code-using-push).</p>

 <p> If you do not plan to commit your own changes, see @(see git-quick-start)
 instead.</p>

 <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 <i>Fork and
 Pull</i> method.</p>

 <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 main 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 directory to match the latest
 contents of the main ACL2 repository on GitHub.</p>

 @({
 git fetch --all
 git merge -m "Merge." remotes/upstream/master
 })

 <h2>(C) CONTRIBUTING</h2>

 <h3>Make Changes and Test Them</h3>

 <ol>

 <li>Before beginning your edits, update, as in (B) above.</li>

 <li>Build an executable.

 @({
 make update LISP=<your_lisp>
 })</li>

 <li>Make book changes.  See the guidelines in the @(see how-to-contribute) topic
  (e.g., about updating the book release notes).</li>

 <li>Run a regression.

 @({
 (make -j 8 regression) >& 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 3 above to make appropriate
 changes and re-test.</li>

 <li>Commit your changes.  First do @('git status') to see the list of all
 new/changed files:

 @({
 git status
 })

 Ensure that none of the reported additions/changes was unintentional.  Next,
 do @('git add') to add each file you want to commit (normally, everything
 reported by @('git status'), to match what was tested in the regression above):

 @({
 git add <file1> <file2> ...
 })

 Now commit your changes locally:

 @({
 git commit -m '<some message, with descriptive first line>'
 })

 The @('-m ...')  option is a log message, where the first line is a summary
 of your changes and additional lines give more details.  You can replace
 the @('-m ...') option by @('-F <filename>'), where @('<filename>') is the
 name of a file that contains your log message.</li>

 <li>Merge in remote changes, if any, by updating again as in (B) above.

 If the merge changed anything, go back to Step 4 above to ensure that your
 changes are compatible with the remote changes you just obtained.  If the
 merge did not change anything, continue to the next step (Contribute Your
 Changes).

 In rare cases, you may get a merge conflict (concurrent changes to the same
 files), in which case you will need to resolve the conflict by editing files
 and committing them (see the @('git commit') command above in Step 7).  Then
 go back to Step 4 above to test that everything is working.

 </li>

 </ol>

 <h3>Contribute Your Changes</h3>

 <p>The following command will update your fork on GitHub.</p>

 @({
  git push
 })

 You now need to create a <i>pull request</i>, where you request that changes
 from your fork be accepted into the main ACL2 repository.
 To achieve this:

 <ol>

 <li>Go to @('https://github.com/<your-github-username>/acl2').</li>

 <li>Click the @('New 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 a description of your changes in the comments section.
 You may want to quote text from your commit log messages.</li>

 <li>Click @('Create pull request').</li>

 </ol>
 At this point, the main ACL2 repository maintainers will be notified,
 check that things seem to be in order, and then either request modifications
 or adopt your changes.")
other
(defxdoc goal-spec
  :parents (hints output-controls)
  :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
 descendants.</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>You can probably figure out the naming conventions for goals after seeing
 some examples in prover output.  Let's discuss the use of the character @(''')
 for a suffix.  If a goal has a single subgoal then a prime is added; e.g., if
 @('"Subgoal 3.2"') has a single subgoal then it is named @('"Subgoal
 3.2'"') rather than @('"Subgoal 3.2.1"').  If in turn that goal has a
 single subgoal, it is named @('"Subgoal 3.2''"'); and so on.  When four or
 more primes would be generated, say, @('n') primes, then the suffix is
 @('"'n'"'); e.g., continuing the preceding example we get @('"Subgoal
 3.2'''"'), @('"Subgoal 3.2'4'"'), @('"Subgoal 3.2'5'"'), and so on.  If
 any of these generates at least two subgoals then any ``prime'' suffix is
 dropped; for example, if @('"Subgoal 3.2'5'"') has two subgoals then they
 are named @('"Subgoal 3.2.2"') and @('"Subgoal 3.2.1"').</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)))
 })")
other
(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. (That can be risky; 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>")
other
(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>")
other
(defxdoc gratuitous-lambda-object-restrictions
  :parents (apply$)
  :short "Enforcement of logically unnecessary restrictions on @(':FN') slots"
  :long "<p>When a form is submitted to the ACL2's read-eval-print loop the
  terms in it are translated (``macroexpanded'') into ACL2's internal form, in
  which abbreviations like @('(cadr x)') are expanded away and constants are
  always quoted.  See @(see term) for details of the internal form.</p>

  <p>But translation also enforces a logically unnecessary restriction in
  argument positions of @(see ilk) @(':FN').  If a quoted @('consp') object
  whose @('car') is the symbol @('LAMBDA') occurs in a @(':FN') slot, translate
  insists that the object satisfy @(tsee well-formed-lambda-objectp).
  Well-formedness implies tameness, so any @('LAMBDA') object that passes this
  translate-time test will have the ``expected behavior'' under @('apply$').
  If a quoted ill-formed ``LAMBDA-like'' object is passed into a @(':FN')
  slot, an error is signaled.</p>

  <p>This is logically unnecessary because, like all ACL2 functions,
  @('apply$') can be called on any objects.  Indeed, ill-formed
  @('LAMBDA')-like objects induce some kind of default behavior by @('apply$')
  and can, sometimes, deliver non-erroneous values.</p>

  <p>But ground @('apply$') terms can be evaluated more quickly on well-formed
  @('LAMBDA') objects than on ill-formed ones.  See for example the discussion
  of performance in @(tsee print-cl-cache).  So this restriction is really
  motivated by a desire to encourage the exclusive use of well-formed
  @('LAMBDA') objects.</p>

  <p>Why would you want to call @('apply$') on ill-formed input?  The answer is
  that you might be trying to explore the semantics of @('apply$') by example.
  Since this is a time-honored methodology, we have made it possible to
  circumvent the translate-time check if you insist on feeding an ill-formed
  object into a @(':FN') slot.  Soundness is not imperiled but execution may
  slow down.</p>

  <p><i>Warning</i>: Using an ill-formed @('LAMBDA') object in a @(':FN') slot
  in a @('defun') will make it impossible to warrant the newly defined function
  because it will not pass the stringent tests necessary to analyze its ilks.
  See @(tsee defwarrant).  Basically these bypasses are intended primarily for
  top-level input to ACL2's read-eval-print loop.</p>

  <p>There are two ways to bypass the check.  Bypass 1 is to construct the
  object in place rather than supply a quoted constant.  This can be as simple
  as consing a @('LAMBDA') onto the rest of your ill-formed constant.  This, of
  course, costs one cons at eval-time.  Bypass 2 is to cons the ill-formed object
  together in a @(tsee defconst) and then use the defined constant symbol in
  the @(':FN') slot.  We illustrate these and other points below.</p>

  @({

  ; Here we show the error that occurs if you use an ill-formed
  ; LAMBDA object in a :FN slot.

  ACL2 !>(apply$ '(lambda (t) (cons t t)) '(a))

  ACL2 Error in TOP-LEVEL: The second element of a well-formed
  LAMBDA object or lambda$ term must be a true list of distinct
  legal variable symbols and (T) is not.  See :DOC
  gratuitous-lambda-object-restrictions for a workaround if you
  really mean to have an ill-formed LAMBDA-like constant in your
  code.  Note: this error occurred in the context
  (APPLY$ '(LAMBDA (T) (CONS T T)) '(A)).

  ; Bypass 1:  Cons the ill-formed object together in place.

  ACL2 !>(apply$ (cons 'lambda '((t) (cons t t))) '(a))
  (A . A)

  ; Bypass 1 (more attractive but perhaps too subtle): Use
  ; backquote.  This looks prettier, indeed, it is almost
  ; unnoticeable!  But it does more eval-time consing.

  ACL2 !>(apply$ `(lambda (t) (cons t t)) '(a))
  (A . A)

  ; Bypass 2:  Use defconst first.  No runtime consing.

  ACL2 !>(defconst *my-ill-formed-lambda*
            `(lambda (t) (cons t t)))
  ...output elided...

  ACL2 !>(apply$ *my-ill-formed-lambda* '(a))
  (A . A)

  ; You can, of course, use these bypasses when defining new
  ; functions.

  ACL2 !>(defun foo (x) (apply$ *my-ill-formed-lambda* (list x)))
  ...successful defun output elided...

  ; You can then execute the new function, possibly slowly.

  ACL2 !>(foo 'b)
  (B . B)

  ; But you can't warrant the new function because defwarrant
  ; can't determine the ilks.

  ACL2 !>(defwarrant foo)

  ACL2 Error in DEFWARRANT: FOO will not be warranted because
  a :FN slot in its body is occupied by a quoted cons object,
  '(LAMBDA (T) (CONS T T)), that is not a well-formed,
  fully-translated, closed ACL2 lambda object. ...

  ; Thus, you can't apply$ 'foo either.

  ACL2 !>(apply$ 'foo '(c))

  ACL2 Error in TOP-LEVEL: The value of APPLY$-USERFN is not
  specified on FOO because FOO has not been warranted.
  })

  <p>By the way, @(':FN') slots are treated differently in another way by
  translate: @(tsee lambda$) terms are <i>only</i> allowed in @(':FN') slots.
  This restriction is necessary for ACL2's correct operation.  @('Lambda$')
  expands differently in the logic than it does in the underlying Common Lisp.
  If @('lambda$') terms were allowed to occur anywhere, this difference could
  be detected by the difference between proved behavior and computed behavior
  and could be used to render ACL2 unsound.</p>")
other
(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>")
other
(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 @(see guard)
 theorem (i.e., guard proof obligation) for a given function symbol, as would
 be generated by a @(':')@(tsee guard-theorem) @(see lemma-instance) in a
 @(':')@(see use) hint.</p>

 @({
 Example Forms:
 :gthm FN
 (gthm 'FN)              ; equivalent to the above
 (gthm 'FN :limited nil) ; equivalent to the above
 (gthm 'FN :limited t)   ; include guard-debug info
 (gthm 'FN nil)          ; avoid any simplification

 General Forms:
 :gthm FN ; equivalent to (gthm 'FN)
 (gthm x &optional simplify guard-debug)
 })

 <p>where @('FN') is a function symbol and @('x') evaluates to a function
 symbol.  Evaluation returns the guard theorem as a user-level (untranslated)
 @(tsee term).  The optional argument @('simplify'), described below, is
 @(':limited') 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 partially 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
 @('simplify') argument should be @('nil') to avoid such simplification; that
 is, use @('(gthm 'FN nil)').  See also @(see guard-simplification) for
 discussion of simplification done for various guard formula utilities.</p>

 <p>Note that the result from evaluating @('(gthm x simplify guard-debug)') is
 an <i>untranslated</i> term, that is, a user-level term; see @(see term).
 The corresponding call @('(guard-theorem x simplify guard-debug (w state)
 state)') returns a translated term.</p>")
other
(defxdoc guarantees-of-the-top-level-loop
  :parents (soundness ld)
  :short "Guarantees provided by top-level evaluation"
  :long "<p>We often refer to the ``top-level loop,'' or just ``the loop'' when
  the context is understood.  The loop is the interactive read-eval-print loop
  with which the user interacts to issue commands, query the ACL2 logical
  world, test functions, conjectures, and systems, etc.  This documentation
  topic mainly addresses the logical guarantees of the loop.  For practical
  advice about interacting with and configuring the loop see @(tsee ld).
  @('Ld') is the ACL2 implementation of the loop (as a macro that calls a
  @(tsee state)-using function with many parameters which may be set by the
  user).  @('Ld') is called initially when ACL2 is fired up.</p>

  <p>But here we are concerned with what it means, logically, when a term
  <i>tm</i> evaluates without error to a value <i>v</i> in the loop.</p>

  <p>We do not formalize macroexpansion here, but rather, we deal with
  so-called &ldquo;translated&rdquo; @(see term)s, where macros and constants
  have been expanded away.  We also do not discuss here how ACL2 evaluates
  expressions; see @(see evaluation) for such discussion.
  (Those interested in implementation issues may also read the long comment in
  ACL2 source file @('interface-raw.lisp') that is labeled &ldquo;Essay on
  Evaluation in ACL2&rdquo;.)</p>

  <p>See @(see soundness) for a more general discussion of soundness-related
  issues (including, for example, interrupts and trust tags).</p>

  <h3>A Strawman Proposal on the Meaning of Top-Level Evaluation</h3>

  <p>One might like to think that for any term, <i>tm</i>, a non-erroneous
  interaction like</p>

  <code>
  ACL2 !&gt;<i>tm</i>
  <i>v</i>
  </code>

  <p>means that the formula</p>

  <code>
  (equal <i>tm</i> '<i>v</i>)
  </code>

  <p>is a theorem and can be proved by the prover.</p>

  <p>For example, let @('sq') be a :logic mode function that squares its
  argument.  (For the sake of a later example, let us also make the @(see
  guard) of @('sq') be @('t') and verify the guard by fixing (with @(tsee
  rfix)) the argument to be a rational, but those aspects of @('sq') are
  irrelevant in our immediate use of it below.)</p>

  <code>
  (defun sq (x)
    (declare (xargs :guard t :verify-guards t))
    (let ((x (rfix x)))
      (* x x)))
  </code>

  <p>then the evaluation</p>

  <code>
  ACL2 !&gt;(sq 3)
  9
  </code>

  <p>suggests that @('(equal (sq 3) 9)') is a theorem and that is indeed
  provable by the ACL2 theorem prover.</p>

  <p>But the situation is quite subtle and deserves further discussion.  That
  is what this topic is about.</p>

  <p><b>Spoiler Alert</b>: We will not give logical semantics to every
  non-erroneous evaluation in this discussion.  We only hint at how it can be
  done for many terms.  Furthermore, even for those terms whose evaluations do
  correspond to theorems, the logical theory in which those theorems can be
  proved is not the theory supported by the ACL2 prover but an extension of it.
  We ultimately describe below the so-called <i>evaluation theory</i> which is
  an extension of ACL2's <i>proof theory</i>.  So this documentation topic
  discusses two logical theories.  Because any theory in which proofs are done
  might be called the ``proof theory'' and in this section we need to clearly
  distinguish between the two theories being discussed, we'll refer to the
  theory supported by the ACL2 theorem prover as the <i>prover's
  theory</i>.</p>

  <h3>Problems Raised by @(':Program') Mode Functions</h3>

  <p>Suppose @('prog-sq') is defined as a @(':')@(tsee program) mode function
  that squares its argument.  Then the top-level evaluation</p>

  <code>
  ACL2 !&gt;(prog-sq 3)
  9
  </code>

  <p>clearly should not suggest</p>

  <code>
  (equal (prog-sq 3) 9)
  </code>

  <p>is a theorem.  @(':Program') mode functions are not defined in the
  prover's theory.  (@(':Program') mode functions may not terminate and any
  naive attempt to add their definitions to the prover's theory as axioms could
  result in unsoundness.)  The top-level loop has the ability to evaluate
  @(':program') mode expressions but it is ``magic,'' unsupported by proof.
  (Non-termination by the evaluator can't manifest unsoundness: such
  computations just never produce an answer.)  The evaluation of @(':program')
  mode expressions is supported in the loop primarily as a way to execute
  commands like @(tsee defun) and @(tsee defthm).  But it is also a convenience
  that allows ACL2 to be used as a @(see programming) language (e.g., to
  prototype a system one might eventually admit to the logic and prove theorems
  about).</p>

  <p>Therefore, when attempting to define the logical meaning of top-level
  evaluations we might restrict our attention to @(':')@(tsee logic) mode terms
  only.  But this is not sufficient for several reasons.</p>

  <p>@(':Program') mode functions raise another problem discussed below in
  connection with @('apply$').</p>

  <h3>Problems Raised by Single-Threaded Objects</h3>

  <p>Evaluation of terms involving single-threaded objects or ``@(see stobj)s''
  raise problems, even if the terms involved are in @(':logic') mode.  Here is
  a top-level evaluation sequence</p>

  <code>
  ACL2 !&gt;(defstobj st fld)
  ...
  ST
  ACL2 !&gt;(update-fld 3 st)
  &lt;st&gt;
  ACL2 !&gt;(update-fld (sq (fld st)) st)
  &lt;st&gt;
  ACL2 !&gt;(fld st)
  9
  </code>

  <p>but the strawman conjecture from the last evaluation, @('(equal (fld st)
  9)'), is not a theorem.  However, a related formula is a theorem and can be
  proved by the prover.</p>

  <code>
  (implies (stp st)
           (let* ((st (update-fld 3 st))
                  (st (update-fld (sq (fld st)) st)))
             (equal (fld st) 3)))
  </code>

  <p>This reminds us that the top-level loop tracks changes to each ``live''
  stobj and records them in the ACL2 @(tsee state).  Those changes must be
  reflected in any suggested theorems.</p>

  <h3>Problems Raised by Apply$</h3>

  <p>@(tsee Apply$) calls @(tsee apply$-userfn) to handle the application of
  user-defined function symbols.  @('Apply$-userfn') is undefined but might be
  constrained by @(tsee warrant) hypotheses (see @(tsee defwarrant)).  Recall
  that warrants link the functions approved by @('defwarrant') to their names
  and constrain @('(apply$ 'fn (list a1 ... an))') to be @('(fn a1 ... an)')
  under certain @(tsee tame)ness conditions.  As noted at the bottom of the
  discussion of @(tsee defwarrant), there is a model of the prover's theory in
  which all warrants issued by @('defwarrant') are true.  The top-level loop
  assumes that all those warrants are true.  But the prover's theory does not,
  because explicit warrant hypotheses are essential to avoiding the so-called
  ``local problem'' (see <b>Lesson 12</b> of @(see
  introduction-to-apply$)).</p>

  <p>One might wonder why we have warrants at all, aside from the local
  problem.  The key reason is that inconsistency can result from
  non-terminating recursion if we had the following
  axiom schema</p>

  <code>
  <b>Unsound Axiom Schema</b>:
  (equal (apply$ '<i>f</i> (list a1 ... an)) (<i>f</i> a1 ... an))
  </code>

  <p>for every defined function <i>f</i>.  See the @('russell') example in
  @(see introduction-to-apply$).  So warrants and the restrictions enforced by
  @(tsee defwarrant) keep the prover's theory consistent.  One might then ask
  ``how do we get away with letting the top-level loop @('apply$') all badged
  @(':program') mode functions?''  The answer is simple: @(':program') mode
  functions are not axiomatized so we don't have a theory to worry about!</p>

  <p>To illustrate the difference between the behavior of the top-level loop
  and the prover, suppose the function @('sq'), defined above, has been
  warranted.</p>

  <code>
  (defwarrant sq)
  </code>

  <p>and then consider the top-level evaluation</p>

  <code>
  ACL2 !&gt;(apply$ 'sq '(3))
  9
  </code>

  <p>This is possible because the warrant for @('sq') is assumed true in the
  top-level loop and that warrant tells the loop that @('(apply$ 'sq '(3))') =
  @('(sq 3)').</p>

  <p>However, @('(equal (apply$ 'sq '(3)) '9)') is not a theorem in the
  prover's theory.  Instead, this is a theorem</p>

  <code>
  (implies (warrant sq)
           (equal (apply$ 'sq '(3)) '9))
  </code>

  <p>where @('(warrant sq)') is just a convenient abbreviation for
  @('(force (apply$-warrant-sq))').</p>

  <p>Thus, to extend the strawman conjecture to functions in which @('apply$')
  is ancestral would require tracking the warrants relevant to the execution
  path (or punting and collecting all warrants) and amending the conjecture to
  add those warrants as hypotheses to the equality.</p>

  <p>But @('apply$') introduces another source of complexity: mixed-mode
  functions (see @(see mixed-mode-functions)).  Recall the @(':program') mode
  function @('prog-sq') which squares its argument.  We can assign a badge to
  @('prog-sq') and then define a @(':logic') mode function that @('apply$')s
  it!</p>

  <code>
  (defbadge prog-sq)

  (defun logic-sq (x)
    (declare (xargs :mode :logic))
    (apply$ 'prog-sq (list x)))
  </code>

  <p>Since the top-level loop can evaluate applications of @(':program') mode
  symbols we see the following evaluation.</p>

  <code>
  ACL2 !&gt;(logic-sq 3)
  9
  </code>

  <p>Note that @('(logic-sq 3)') is a @(':logic') mode term and @('logic-sq')
  can even be warranted with @('defwarrant').  But neither</p>

  <code>
  (equal (logic-sq 3) '9)
  </code>

  <p>nor</p>

  <code>
  (implies (warrant logic-sq) (equal (logic-sq 3) '9))
  </code>

  <p>is a theorem in the prover's theory because @('prog-sq') is undefined in
  that theory.  For what it is worth, the prover can prove</p>

  <code>
  (implies (warrant logic-sq) (equal (logic-sq 3) (apply$ 'prog-sq '(3))))
  </code>

  <p>This example contradicts the suggestion, just above, that if we properly
  considered warrants we could give logical meaning to evaluations of
  @(':logic') mode terms involving @('apply$').</p>

  <h3>Problems Raised by Constrained Functions</h3>

  <p>Constrained functions raise problems if they have been given
  attachments (see @(tsee defattach)).  The top-level loop uses attachments to
  compute values consistent with the constraints, but the prover's theory does
  not.  Attachments are useful for building and testing instances of models
  consistent with the constraints.</p>

  <p>For example, let @('(nonneg-rat x)') be constrained to return some
  nonnegative rational.</p>

  <code>
  (encapsulate (((nonneg-rat *) =&gt; *))
    (local (defun nonneg-rat (x)
             (declare (ignore x))
             0))
    (defthm nonneg-rat-constraint
      (and (rationalp (nonneg-rat x))
           (&lt;= 0 (nonneg-rat x)))))
  </code>

  <p>It is impossible to evaluate @('(nonneg-rat 3)') in the top-level loop.
  But we can attach another function to it provided we can prove that function
  always returns a nonnegative rational.  Since @('sq'), as defined above to
  @('rfix') its argument as a rational, satisfies that constraint, we can attach
  @('sq') to @('nonneg-rat').</p>

  <code>
  (defattach nonneg-rat sq)
  </code>

  <p>and then we can ``evaluate'' calls of @('nonneg-rat') in the loop, getting
  results that are consistent with its constraint (but overly specific!).</p>

  <code>
  ACL2 !&gt;(nonneg-rat 3)
  9
  </code>

  <p>But of course the strawman conjecture @('(equal (nonneg-rat 3) '9)') is
  not a theorem of the prover's theory.</p>

  <h3>The Prover's Theory</h3>

  <p>The ACL2 logic formalizes an applicative (functional and side-effect free)
  extension of a subset of Common Lisp (see @(see common-lisp)).  It is
  described in chapter 6 of <a
  href='http://www.cs.utexas.edu/users/moore/publications/acl2-books/car/index.html'>Computer-Aided
  Reasoning: An Approach</a>, by Kaufmann, Manolios, and Moore, as an extension
  of quantifier-free first-order logic with equality (section 6.1).  The syntax
  is that of translated @(see term)s though the user is allowed to use a more
  flexible syntax which can be extended by defining constant symbols and
  macros (see @(tsee defconst) and @(tsee defmacro)).  To see the formal
  translation of such a term use the command @(':')@(tsee trans).  In section
  6.2 of the book, axioms are added to characterize the basic data objects of
  numbers (integers, rationals, and complex rationals), characters, strings,
  symbols, and ordered pairs.  In section 6.3, the ordinals up to epsilon-0 are
  constructed from ordered pairs and integers; a well-founded ``less than''
  relation is also defined.  But the book's construction of the ordinals is now
  obsolete.  A new representation was implemented after the book was published.
  See @(see ordinals).  In Section 6.4, a conservative Principle of
  Definition (see @(tsee defun) and @(tsee defuns) or @(tsee mutual-recursion))
  is introduced, allowing the addition of axioms defining new function symbols.
  In Section 6.5, a Principle of Induction up to epsilon-0 is described.
  Induction and recursion are duals: every admissible recursive function
  suggests an induction and vice versa and this duality is used by the ACL2
  prover to select an often appropriate induction scheme for a conjecture.  See
  @(see induction) and @(tsee hints) for ways to influence this selection.
  Finally, in section 6.6, the book introduces @(tsee encapsulate) to introduce
  constrained functions and functional instantiation (a derived rule of
  inference akin to second order instantiation), and a variety of other ways of
  conservatively adding new function symbols.</p>

  <p>The ACL2 prover proves theorems in the extension of the above theory
  obtained by adding the axioms introduced by @(see events) successfully
  carried out in the user's session.  The most common such axiom-adding events
  are @(tsee defun), @(tsee defchoose), and @(tsee encapsulate), which all
  conservatively extend the theory by the addition of axioms about new function
  symbols.  But @('defun') is just a special case of @('defuns') which adds a
  mutually recursive clique of new names (see also @(tsee mutual-recursion)).
  @(tsee Defstobj) and @(tsee defabsstobj) add recognizers, constructors, and
  accessors for single-threaded objects (aka ``@(see stobj)s'') but logically
  just use @('defun') to add new functions and then syntactically restrict
  their use in code.  Finally, we provide a means of adding an arbitrary
  formula as an axiom, @(tsee defaxiom), but <i>strongly discourage its
  use</i>.  There are many other events that add axioms, e.g., @(tsee defun-nx)
  and @(tsee defun-sk) but these are defined as macros that expand into the
  primitives just listed.  In addition, there is a facility for including files
  of previously admitted events, @(tsee include-book).</p>

  <p>Note that an event of the form @('(skip-proofs EV)') does not introduce
  any axioms other that those added by the event, @('EV').  However, this
  @(tsee skip-proofs) event does assume that all proof obligations introduced
  by @('EV') are indeed provable in the prover's theory.</p>

  <p>Given a user's session, we call the above described theory the <i>prover's
  theory</i>.</p>

  <p>Now recall the strawman proposal for what evaluation in the top-level loop
  means, i.e., that the evaluation</p>

  <code>
  ACL2 !&gt;<i>tm</i>
  <i>v</i>
  </code>

  <p>might mean that the formula</p>

  <code>
  (equal <i>tm</i> '<i>v</i>)
  </code>

  <p>is a theorem.  We have illustrated with @(':program') mode functions, uses
  of @('apply$'), and of constrained functions that this strawman conjecture is
  <i>not</i> necessarily a theorem of the prover's theory!</p>

  <p>However, there is a theory in which many of these conjectures are
  theorems.</p>

  <h3>The Evaluation Theory</h3>

  <p>The <i>evaluation theory</i> is obtained from the prover's theory as
  follows.</p>

  <ul>

  <li>Instead of treating stobj names as variables, the evaluation theory
  treats them as abbreviations for the ``current value'' of the stobj,
  specifically, the constant obtained by composing the sequence of all updates
  to the stobj's fields carried out so far in the top-level loop.  Thus, for
  example, in the evaluation theories created by this sequence of top-level
  evaluations

  <code>
  ACL2 !&gt;(defstobj st fld)                           ; [1]
  ST
  ACL2 !&gt;(update-fld 3 st)                           ; [2]
  &lt;st&gt;
  ACL2 !&gt;(update-fld (* (fld st) (fld st)) st)       ; [3]
  &lt;st&gt;
  </code>

  @('st') is an abbreviation for @('(NIL)') after evaluation [1], an
  abbreviation for @('(3)') after evaluation [2], and an abbreviation for
  @('(9)') after evaluation [3].</li>

  <li>Every warrant created by @('defwarrant') is assumed true as an
  axiom.</li>

  <li>For every @('(defattach f g)') event in the prover's theory the
  axiom (i.e., constraints) on @('f') is replaced by the axiom @('(equal (f
  ...) (g ...))') in the evaluation theory.  (Of course this replacement also
  takes place when using the more general form for @(tsee defattach),
  @('(defattach ... (f g ...) ...)').)</li>

  </ul>

  <p>Given the restrictions enforced by @('defun'), @('defstobj'),
  @('defwarrant'), @('apply$'), @('encapsulate'), and @('defattach'), the
  evaluation theory is consistent if the prover's theory is consistent and free
  of @('defaxiom') events.  (Those interested in reading a proof of this claim
  are welcome to read the &ldquo;Essay on Defattach&rdquo; in ACL2 source file
  @('other-events.lisp').)</p>

  <p>Furthermore, the top-level evaluation</p>

  <code>
  ACL2 !&gt;<i>tm</i>
  <i>v</i>
  </code>

  <p>means that</p>

  <code>
  (equal <i>tm</i> '<i>v</i>)
  </code>

  <p>is a theorem in the evaluation theory provided</p>

  <ul>

  <li><i>tm</i> is a @(':logic') mode term, and</li>

  <li>every symbol that reaches the first argument of any @('apply$-userfn') in
  the execution of <i>tm</i> is in @(':logic') mode.</li>

  </ul>

  <p>The ACL2 prover cannot generally prove these theorems, since it operates
  in the prover's theory.  However, as noted, there are often ways to encode
  the conjectures into ACL2 formulas that are provable &mdash; in particular,
  by adding suitable warrant hypotheses &mdash; though the ACL2 system does not
  provide tools for doing so.</p>

  <h3>Some Examples of Top-Level Evaluations</h3>

  <p>In this section we illustrate some consequences of the guarantee that for
  any term, <i>tm</i>, satisfying certain restrictions, if <i>tm</i> evaluates
  to a value <i>v</i>, then the term</p>

  <code>
  (equal <i>tm</i> '<i>v</i>)
  </code>

  <p>is a theorem of the evaluation theory.</p>

  <p>Each command below is enumerated and after the entire sequence we make
  observations about the results and implications.  It might also help to read
  the section <b>Top-Level Evaluation of Apply$</b> in the documentation for
  @(tsee apply$), which describes how @('apply$') is implemented in the
  top-level loop.</p>

  @({
  ACL2 !>(include-book "projects/apply/top" :dir :system)
  ...
  ACL2 !>(defun my-cons (x y)                                  ; [1]
            (declare (xargs :mode :program))
            (cons x y))
  ...
  ACL2 !>(defbadge my-cons)                                    ; [2]

  MY-CONS now has the badge (APPLY$-BADGE 2 1 . T) but has
  no warrant.

   T
  ACL2 !>(apply$ 'my-cons '(3 4))                              ; [3]
  (3 . 4)
  ACL2 !>(thm (equal (my-cons 3 4) '(3 . 4)))                  ; [4]
  ...
  ******** FAILED ********
  ACL2 !>(verify-termination my-cons)                          ; [5]
  ...
  ACL2 !>(apply$ 'my-cons '(3 4))                              ; [6]


  ACL2 Error in TOP-LEVEL:  The value of APPLY$-USERFN is not
   specified on MY-CONS because MY-CONS has not been warranted.

  ACL2 !>(defwarrant my-cons)                                  ; [7]

  MY-CONS is now warranted by APPLY$-WARRANT-MY-CONS, with
  badge (APPLY$-BADGE 2 1 . T).

  ACL2 !>(apply$ 'my-cons '(3 4))                              ; [8]
  (3 . 4)

  ACL2 !>ACL2 !>(thm (equal (my-cons 3 4) '(3 . 4)))           ; [9]
  ...
  ******** FAILED ********
  ACL2 !>(thm                                                  ;[10]
          (implies (warrant my-cons)
                   (equal (my-cons 3 4) '(3 . 4))))
  ...
  Q.E.D.
  ...
  Proof succeeded.
  })

  <p>In events [1] and [2] @('my-cons') is introduced as a badged @(':program')
  mode function.  Command [3] shows that we can @('apply$') @(''my-cons') in
  the top-level loop and get the ``expected'' value.  This is ``magic'' on
  several levels!  There is no axiom in the evaluation theory defining
  @('my-cons') and there is no warrant connecting the symbol @(''my-cons') to
  the function @('my-cons').  The failure of the first @('thm') command, [4],
  shows that the prover's theory knows nothing of the behavior of @('apply$')
  on @(''my-cons').  After converting @('my-cons') to @(':logic') mode with
  @(tsee verify-termination) in [5] we can no longer evaluate the application
  of @('my-cons') at the top-level, as shown by [6]!  This is surprising
  because one might expect ACL2 to be able to do more with a @(':logic') mode
  function than its @(':program') mode counterpart.  But in the evolving
  evaluation theory as of [6], @('my-cons') is a @(':logic') mode function with
  no warrant and so logically speaking @('(apply$ 'my-cons ...)')  is
  undefined.  Computing a value for it at [6] would violate the guarantee that
  values of @(':logic') mode terms can be proved correct in the evaluation
  theory &mdash; i.e., that the computed value can be derived logically.  Such
  a derivation is impossible without a warrant.  However, after
  @('defwarrant'), in [7], confirms that it is sound to issue a
  warrant (linking the symbol @(''my-cons') to the function @('my-cons') via
  @('apply$')), the evaluation of the @(''my-cons') term in [8] succeeds.  The
  @('defwarrant') soundly extends the proof theory by adding a definition for
  the warrant function for @('my-cons') and extends the evaluation theory by
  assuming the warrant for @('my-cons') is true.  This latter extension is also
  sound.  However, [9] shows that we still cannot prove (in the prover's
  theory) that the evaluation of the @('apply$') term is correct, because we
  did not provide the warrant as a hypothesis.  However, if we amend the
  conjecture to include the warrant, as in [10], the proof (in the prover's
  theory) succeeds.  While all warrants are assumed true in the evaluation
  theory, they must be made explicit as hypotheses for proofs in the prover's
  theory.  This is the mechanism whereby ACL2 can avoid the ``local problem''
  illustrated in <b>Lesson 12</b> of @(see introduction-to-apply$) and
  discussed more thoroughly in <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.</p>")
other
(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>")
other
(defxdoc guard-checking-inhibited
  :parents (evaluation guard)
  :short "Avoiding certain warnings when 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 warning 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>This behavior can occur for a recursively-defined @(see logic)-mode
 function with a guard other than @('t') whose guards have not been verified,
 when @(see guard-checking) has its default value, @('t').  (Exceptions may
 occur, for example when the function is being traced.)  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)
 })")
other
(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 @(see 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>")
other
(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 >
 })")
other
(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.  The @('define-key') command is optional, in case you want to put that
 keyboard macro on a key &mdash; though in that case you'll need to have
 defined @('ctl-t-keymap'), which happens automatically if you load file
 @('emacs-acl2.el'); see :DOC emacs.</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])

  (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.
 })")
other
(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 @(see state) global @('(@ 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; a remark with details for system hackers is at the end of
 this topic.)  Note that @(''guard-checking-on') is set to @('nil') during
 proofs but is set to @('t') during @(tsee certify-book), and @(tsee
 include-book), 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>

 <p>Remark for system hackers.  As noted above, a fifth value, @(':nowarn'), is
 similar to @('t') but suppresses warnings.  Only the four values in the column
 headers above and @(':nowarn') are legal for @(tsee set-guard-checking),
 @(tsee with-guard-checking), @(tsee with-guard-checking-error-triple), and
 @(tsee with-guard-checking-event).  Behavior is technically undefined if you
 set @(see state) global @('guard-checking-on') directly to other than those
 five values, say using @(tsee assign), @(tsee f-put-global), or @(tsee
 state-global-let*).  However, as of this writing (in August 2021), such a
 value will cause the same behavior as value @(':nowarn').  End of
 Remark.</p>")
other
(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 helpful 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 &ldquo;modes&rdquo;:</p>

 <blockquote>

 <p>@(see defun-mode) &mdash; &ldquo;Does this @(see defun) add an
 axiom (&lsquo;logic mode&rsquo;) or not (`:program mode')?&rdquo; (See @(see
 defun-mode).)  Only @(see logic) mode functions can have their &ldquo;@(see
 guard)s verified&rdquo; via mechanized proof; see @(see verify-guards).</p>

 <p>@(tsee set-guard-checking) &mdash; &ldquo;Should runtime @(see guard)
 violations signal an error (@(':all'), and usually with @('t') or
 @(':nowarn')) or go undetected (@('nil'), @(':none'))?  The question relates
 to the use of Common Lisp to evaluate expressions; see @(see
 set-guard-checking).</p>

 </blockquote>

 <h3>Examples of prompts</h3>

 <p>Here are some examples of the relation between the ACL2 @(see prompt) and
 the &ldquo;modes&rdquo; discussed above.  Also see @(see
 default-print-prompt).  The first examples all have @(tsee ld-skip-proofsp)
 equal to @('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) equal to
 @(':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
 })

 <h3>Sample session</h3>

 @({
  ACL2 !>(+ 'abc 3)


  ACL2 Error [Evaluation] in TOP-LEVEL:  The guard for the function call
  (BINARY-+ X Y), which is (AND (ACL2-NUMBERP X) (ACL2-NUMBERP Y)), is
  violated by the arguments in the call (BINARY-+ 'ABC 3).
  See :DOC set-guard-checking for information about suppressing this
  check with (set-guard-checking :none), as recommended for new users.
  To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.

  ACL2 !>:set-guard-checking nil
  [[.. output elided ..]]
  ACL2 >(+ 'abc 3)
  3
  ACL2 >(< 'abc 3)
  T
  ACL2 >(< 3 'abc)
  NIL
  ACL2 >(< -3 'abc)
  T
  ACL2 >:set-guard-checking t

  Turning guard checking on, value T.

  ACL2 !>(defun sum-list (x)
          (declare (xargs :guard (integer-listp x)
                          :verify-guards nil))
          (cond ((endp x) 0)
                (t (+ (car x) (sum-list (cdr x))))))

  The admission of SUM-LIST is trivial, using the relation
  O< (which is known to be well-founded on the domain
  recognized by O-P) and the measure (ACL2-COUNT X).
  We observe that the type of SUM-LIST is described by the
  theorem (ACL2-NUMBERP (SUM-LIST X)).  We used primitive type
  reasoning.

  Summary
  Form:  ( DEFUN SUM-LIST ...)
  Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
  Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.03)
   SUM-LIST
  ACL2 !>(sum-list '(1 2 3))

  ACL2 Warning [Guards] in TOP-LEVEL:  Guard-checking will be inhibited
  for some recursive calls, including SUM-LIST; see :DOC guard-checking-
  inhibited.

  6
  ACL2 !>(sum-list '(1 2 abc 3))


  ACL2 Error [Evaluation] in TOP-LEVEL:  The guard for the function call
  (SUM-LIST X), which is (INTEGER-LISTP X), is violated by the arguments
  in the call (SUM-LIST '(1 2 ABC 3)).
  See :DOC set-guard-checking for information about suppressing this
  check with (set-guard-checking :none), as recommended for new users.
  To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.

  ACL2 !>:set-guard-checking nil
  [[.. output elided ..]]
  ACL2 >(sum-list '(1 2 abc 3))
  6
  ACL2 >(defthm sum-list-append
         (equal (sum-list (append a b))
                (+ (sum-list a) (sum-list b))))

  *1 (the initial Goal, a key checkpoint) is pushed for proof by induction.

  Perhaps we can prove *1 by induction.  Three induction schemes are
  suggested by this conjecture.  Subsumption reduces that number to two.
  However, one of these is flawed and so we are left with one viable
  candidate.

  [[.. output elided ..]]

  *1 is COMPLETED!
  Thus key checkpoint Goal is COMPLETED!

  Q.E.D.

  Summary
  Form:  ( DEFTHM SUM-LIST-APPEND ...)
  Rules: ((:DEFINITION BINARY-APPEND)
          (:DEFINITION ENDP)
  [[.. output elided ..]]
          (:TYPE-PRESCRIPTION SUM-LIST))

  Time:  0.01 seconds (prove: 0.01, print: 0.00, other: 0.00)
  Prover steps counted:  470
   SUM-LIST-APPEND
 })

 <h3>Guard verification for functions</h3>

 <p>See @(see declare), and @(see xargs), and @(see verify-guards) for related
 background, though we intend what follows to be self-explanatory.</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         1  (DEFUN SUM-LIST (X)
                  (DECLARE (XARGS :GUARD (INTEGER-LISTP X)
                                  :VERIFY-GUARDS NIL))
                  (COND ((ENDP X) 0)
                        (T (+ (CAR X) (SUM-LIST (CDR X))))))
  ACL2 >(verify-guards sum-list)

  Computing the guard conjecture for SUM-LIST....

  The non-trivial part of the guard conjecture for SUM-LIST, given the

  [[.. output elided ..]]

  Q.E.D.

  That completes the proof of the guard theorem for SUM-LIST.  SUM-LIST
  is compliant with Common Lisp.

  Summary
  Form:  ( VERIFY-GUARDS SUM-LIST)
  Rules: ((:DEFINITION ENDP)
  [[.. output elided ..]]
          (:TYPE-PRESCRIPTION SUM-LIST))
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
  Prover steps counted:  115
   SUM-LIST
  ACL2 >:pe sum-list
   LV        1  (DEFUN SUM-LIST (X)
                  (DECLARE (XARGS :GUARD (INTEGER-LISTP X)
                                  :VERIFY-GUARDS NIL))
                  (COND ((ENDP X) 0)
                        (T (+ (CAR X) (SUM-LIST (CDR X))))))
  ACL2 >:set-guard-checking t

  Turning guard checking on, value T.

  ACL2 !>(sum-list '(1 2 abc 3))


  ACL2 Error [Evaluation] in TOP-LEVEL:  The guard for the function call
  (SUM-LIST X), which is (INTEGER-LISTP X), is violated by the arguments
  in the call (SUM-LIST '(1 2 ABC 3)).
  See :DOC set-guard-checking for information about suppressing this
  check with (set-guard-checking :none), as recommended for new users.
  To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.

  ACL2 !>:set-guard-checking nil
  [[.. output elided ..]]
  ACL2 >(sum-list '(1 2 abc 3))
  6
  ACL2 >
  })

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

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

  <h3>Guard verification for theorems</h3>

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

  @({
  ACL2 >:pe sum-list-append
             2  (DEFTHM SUM-LIST-APPEND
                  (EQUAL (SUM-LIST (APPEND A B))
                         (+ (SUM-LIST A) (SUM-LIST B))))
  ACL2 >(verify-guards sum-list-append)

  Computing the guard conjecture for SUM-LIST-APPEND....

  The non-trivial part of the guard conjecture for
  SUM-LIST-APPEND, given the :type-prescription rule SUM-LIST,
  is

  Goal
  (AND (TRUE-LISTP A)
       (INTEGER-LISTP A)
       (INTEGER-LISTP (APPEND A B))
       (INTEGER-LISTP B)).

  ******** FAILED ********
  ACL2 >
  })

  <p>Perhaps surprisingly, a @(tsee defthm) event with statement</p>

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

  <p>is still not guard-verifiable.  The reason is that @(tsee implies) is a
  function, so its arguments are both always evaluated &mdash; in particular,
  its second argument is evaluated even if its first argument evaluates to
  @('nil').  Here is a way to fix that problem.</p>

  @({
  ACL2 >(defthm common-lisp-sum-list-append
           (if (and (integer-listp a)
                    (integer-listp b))
               (equal (sum-list (append a b))
                      (+ (sum-list a) (sum-list b)))
               t)
           :rule-classes nil)

  Q.E.D.

  Summary
  Form:  ( DEFTHM COMMON-LISP-SUM-LIST-APPEND ...)
  Rules: ((:REWRITE SUM-LIST-APPEND))
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
  Prover steps counted:  23
   COMMON-LISP-SUM-LIST-APPEND
  ACL2 >(verify-guards common-lisp-sum-list-append)

  Computing the guard conjecture for COMMON-LISP-SUM-LIST-APPEND....

  The non-trivial part of the guard conjecture for COMMON-LISP-SUM-LIST-APPEND,
  given the :forward-chaining rules ACL2-NUMBER-LISTP-FORWARD-TO-TRUE-LISTP,
  INTEGER-LISTP-FORWARD-TO-RATIONAL-LISTP and
  RATIONAL-LISTP-FORWARD-TO-ACL2-NUMBER-LISTP and the :type-prescription
  rules ACL2-NUMBER-LISTP, INTEGER-LISTP, RATIONAL-LISTP and SUM-LIST,
  is

  Goal
  (IMPLIES (AND (INTEGER-LISTP A)
                (INTEGER-LISTP B))
           (INTEGER-LISTP (APPEND A B))).

  [[.. output elided ..]]

  Q.E.D.

  That completes the proof of the guard theorem for
  COMMON-LISP-SUM-LIST-APPEND.  COMMON-LISP-SUM-LIST-APPEND is compliant
  with Common Lisp.

  Summary
  Form:  ( VERIFY-GUARDS COMMON-LISP-SUM-LIST-APPEND)
  Rules: ((:DEFINITION BINARY-APPEND)
  [[.. output elided ..]]
          (:TYPE-PRESCRIPTION SUM-LIST))
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
  Prover steps counted:  565
   COMMON-LISP-SUM-LIST-APPEND
  ACL2 >
 })

 <p>Guard verification fails when the theorem is for &ldquo;code&rdquo; that
 cannot even be parsed (or &ldquo;translated&rdquo;; see @(see term)) as
 executable code.</p>

 @({
  ACL2 >(defthm foo (consp (mv x y)))

  Q.E.D.

  The storage of FOO depends upon primitive type reasoning.

  Summary
  Form:  ( DEFTHM FOO ...)
  Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   FOO
  ACL2 >(verify-guards foo)


  ACL2 Error in ( VERIFY-GUARDS FOO):  The guards for FOO cannot be verified
  because its formula has the wrong syntactic form for evaluation, perhaps
  due to multiple-value or stobj restrictions.  See :DOC verify-guards.


  Summary
  Form:  ( VERIFY-GUARDS FOO)
  Rules: NIL
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)

  ACL2 Error [Failure] in ( VERIFY-GUARDS FOO):  See :DOC failure.

  ******** FAILED ********
  ACL2 >
 })")
other
(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>@(tsee 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>@(tsee Guard-obligation): This function is a programmatic version of the
 macro, @(tsee verify-guards-formula).  It provides the guard obligation as a
 set of @(see clause)s, 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>@(tsee 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>@(tsee 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.</p>

 <ul>

 <li>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.</li>

 <li>The level of simplification differs between the two pairs.  See @(see
 guard-simplification) for a detailed explanation; here are highlights.  The
 first pair simplifies (by default) 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.</li>

 <li>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.</li>

 </ul>")
other
(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.  Such
 removal is performed in some other settings as well, including @(see hints)
 processing, generating proof obligations for @(see guard)s and termination,
 and the storing of induction schemes and @(see constraint)s.</p>

 <p>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)), usually including
 quoted lambda expressions that appear in an argument position with @(see ilk)
 @(':FN') (see @(see apply$)).</p>

 @({
 (return-last term0 term1 term2)  ==>  term2

 (mv-list n term)                 ==>  term

 (cons-with-hint x y)             ==>  (cons x y)

 (the-check guard x y)            ==>  y

 (from-df x)                      ==>  x

 (to-df 'r)                       ==>  'r ; only when r satisfies dfp

 (df0)                            ==>  0

 (df1)                            ==>  1

 (do$ x1 x2 x3 x4 x5 'u1)         ==> (do$ x1 x2 x3 x4 x5 'nil)
                                      ; only when u1 is non-nil

 ; 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

 ; For other than measure theorems and induction schemes, remove lambda
 ; applications that are ``trivial'' in either of the following two senses.

 ; For replacing a term (let ((v term)) v) by term:
 (('LAMBDA (v) v) term)           ==>  term

 ; When each formal is equal to the corresponding actual:
 (('LAMBDA (f1 ... fk) body)
  f1 ... fk)                      ==>  body
 })

 <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>

 <p>The final two classes of simplification above (removal of ``trivial''
 lambda applications) may be removed by executing the following form, which is
 @(tsee local) to an @(tsee encapsulate) form and to @(see books).</p>

 @({
 (defattach-system remove-guard-holders-lamp constant-nil-function-arity-0)
 })

 <p>Here is how to restore the default behavior.</p>

 @({
 (defattach-system remove-guard-holders-lamp constant-t-function-arity-0)
 })

 <p>Note that by default, guard-holders are not removed inside calls of @(tsee
 hide).  You can however cause them to be removed inside such calls after all,
 as was the case through Version  8.2, as follows.</p>

 @({
 (defattach-system ; generates (local (defattach ...))
   remove-guard-holders-blocked-by-hide-p
   constant-nil-function-arity-0)
 })")
other
(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>")
other
(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>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
 exceptions to this rule are that all @(':stobjs') and @(':dfs') declarations
 will be treated as through they precede all @(':guard') and @('type')
 declarations.</p>")
other
(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 t 'top-level state)
  (guard-obligation '(if (consp x) (foo (car x)) t) nil nil t 'my-fn state)

  General Forms:
  (guard-obligation name rrp guard-debug guard-simplify ctx state)
  (guard-obligation term rrp guard-debug guard-simplify 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)); @('guard-simplify') is typically @('t') but may be
 @(':limited') (see @(see verify-guards)); @('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 guard-simplify '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 guard-simplify 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 @(see clause)s (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>")
other
(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>")
other
(defxdoc guard-simplification
  :parents (guard-formula-utilities)
  :short "Levels of simplification for @(see guard) proof obligations"
  :long "<p>ACL2 provides several features for obtaining the proof obligations
 generated for @(see guard) verification.  Each of these features can be
 invoked with an argument that controls the level of simplification to be
 applied before returning those proof obligations.  This topic examines those
 simplification levels.  It starts by splitting the features into two groups;
 then continues by explaining the three levels of simplification; and finally,
 makes the key point that one group allows the top two levels of simplification
 and the other group allows the bottom two levels.</p>

 <p>These features can be partitioned into two groups, which we reference below
 as the ``<b>AT</b>'' and ``<b>AFTER</b>'' groups, as follows.  These
 correspond respectively to the two groups discussed in the documentation
 topic, @(see guard-formula-utilities), for capturing formulas produced either
 during guard verification or when a @(':guard-theorem') is supplied for a
 @(':use') hint.</p>

 <ul>

 <li>Simplification <b>AT</b> guard-verification time:<br/>

 <ul>

 <li>the @(tsee xargs) keyword @(':guard-simplify'),</li>

 <li>the @(tsee guard-obligation) utility, and</li>

 <li>the @(tsee verify-guards-formula) utility.</li>

 </ul></li>

 <li>Simplification <b>AFTER</b> guard-verification time:<br/>

 <ul>

 <li>the @(':')@(tsee gthm) utility, and</li>

 <li>the @(':')@(tsee guard-theorem) @(see lemma-instance) (and related
 low-level utility, @('guard-theorem').</li>

 </ul></li>

 </ul>

 <p>Each feature above has an argument (possibly optional) that controls the
 level of simplification.  Each such argument can take any of three values, as
 follows.  But <b>NOTE</b>: @('T') and @(':LIMITED') are the only legal values
 for the &ldquo;AT&rdquo; (first) group, and @(':LIMITED') and @('NIL') are the
 only legal values for the &ldquo;AFTER'' (second) group.</p>

 <ul>

 <li>@('T'):<br/>
 Full simplification, which is the default behavior for @(tsee
 verify-guards)</li>

 <li>@(':LIMITED'):<br/>
 Reduced simplification, skipping simplifications that depend on the set of
 currently @(see enable)d rules</li>

 <li>@('NIL'):<br/>
 No simplification</li>

 </ul>

 <p>The key point of this topic is the following specification of the values
 allowed for the simplification argument, for the features in each group.  For
 features in the <b>AT</b> group, @('T') and @(':LIMITED') are the legal
 values.  For features in the <b>AFTER</b> group, @(':LIMITED') and @('NIL')
 are the legal levels.  Let's see why this is reasonable and discuss whether
 the missing value for each group might be allowed in the future.</p>

 <p>First consider the <b>AFTER</b> group.  A @(':')@(tsee guard-theorem)
 @(':use') hint obtains the @(see guard) theorem proved for a previously
 guard-verified function.  The @(tsee current-theory) at the time of that
 @(':use') hint may be very different from what it was at guard-verification
 time.  Thus, when processing that hint it would be misleading to allow the
 current @(see theory) to participate in simplification that produces the guard
 theorem, since the result could be very different from the guard theorem
 generated during the earlier guard verification.  That is why the value @('T')
 is not allowed for the simplification argument of a @(':')@(tsee
 guard-theorem) hint.  Instead, the default is @(':LIMITED').  The @(tsee gthm)
 utility provides a way to show the formula that would be provided by a
 @(':guard-theorem') lemma instance, so @('gthm') also disallows @('T'), and
 its default is also @(':LIMITED').  Note that the utility @(tsee
 verify-guards-formula) is more appropriate than @('gthm') to view the formula
 to be proved if one is about to verify guards for a function.  (If @('gthm')
 were to be used for that purpose too, then @('T') might be allowed as a
 simplification argument; but that could lead to confusion, in particular about
 the default.)</p>

 <p>Now consider the <b>AT</b> group, which relates to guard verification.
 @('T') is a reasonable default: it is generally useful to maximize
 simplification while generating the guard theorem before attempting its proof.
 But one may prefer more control, by avoiding simplification until the proof is
 attempted.  @(':LIMITED') has proved to be a good compromise: it limits
 simplification to basic operations, in particular avoiding goals that are
 subsumed by other goals or are instances of trivial @(see built-in-clause)
 rules.  If the need arises to support @('NIL') as a simplification value,
 perhaps ACL2 will change to support that.</p>")
other
(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 returns
 a translated @(see term).  It is essentially the functional version of the
 @('gthm') macro, which however returns an untranslated term.  See @(see
 gthm).</p>")
other
(defxdoc guard-theorem-example
  :parents (lemma-instance guard
    hints
    guard-theorem
    guard-formula-utilities)
  :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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(defxdoc hands-off-lambda-objects-theory
  :parents (theories theory-functions rewrite)
  :short "how to specify no modification of lambda objects"
  :long "<p>The enabled status of two @('rewrite-lambda-modep') runes are used
  as flags to determine the action taken when eligible @('lambda') objects are
  encountered by the ACL2 rewriter.  See @(see rewrite-lambda-object) and
  @(tsee rewrite-lambda-object-actions).  To prevent the rewriter even
  considering changing a quoted @('lambda') object, the rune
  @('(:executable-counterpart rewrite-lambda-modep)') must be disabled in the
  then-current theory.  The 0-ary function @('hands-off-lambda-objects-theory')
  returns such a theory.</p>

  <p>In fact, diving into eligible quoted @('lambda') object constants to
  rewrite the body is the default action when ACL2 starts up.  See @(see
  rewriting-versus-cleaning-up-lambda-objects) for why you might want to change
  the default action when eligible @('lambda') objects are encountered by the
  rewriter.</p>

  <p>The expression @('(hands-off-lambda-objects-theory)') macroexpands to the
  theory expression</p>

  @({
  (e/d nil
       ((:executable-counterpart rewrite-lambda-modep)))
  })

  <p>which is a theory equal to the current theory except that the
  executable-counterpart rune of @('rewrite-lambda-modep') is disabled.  This
  expansion is suitable for use in an @(tsee in-theory) event or
  @(':in-theory') hint (see @(':')@(tsee hints)).</p>

  <p>This rune is initially enabled, so eligible @('lambda') object bodies are
  either rewritten or syntactically cleaned by default (depending on the status
  of @('(:definition rewrite-lambda-modep)')) until and unless some
  event (e.g., an @(tsee in-theory) or @(tsee include-book)) or a superior
  local subgoal hint changes the status of this rune.</p>

  <p>For example, if @('lambda') object rewriting is active and you wish it not
  to be (so that @('lambda') objects remain unchanged) in @('Subgoal 3') of
  some proof, you could use the @(':')@(tsee hints)</p>

  @({
  ("Subgoal 3"
   :in-theory (hands-off-lambda-objects-theory))
  })

  <p>Note that if you also wish to enable or disable other runes in the same
  subgoal you must construct an appropriate theory.</p>

  <p>For example, if in @('Subgoal 3') of some proof you wanted to enable
  @('LEMMA1') and disable @('LEMMA2') in a theory that will also specify
  syntactic cleaning of @('lambda') objects, you might write</p>

  @({
  ("Subgoal 3"
   :in-theory (set-difference-theories
                 (union-theories (hands-off-lambda-objects-theory)
                                 '(LEMMA1))
                 '(LEMMA2)))
  })

  <p>Some users might prefer</p>

  @({
  ("Subgoal 3"
   :in-theory (e/d (LEMMA1)
                   ((:executable-counterpart rewrite-lambda-modep)
                    LEMMA2)))
  })

  <p>See @(see theories) for general information about theories and how to
  create and use them.</p>")
other
(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)")
other
(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)")
other
(defxdoc heavy-linear-p
  :parents (linear-arithmetic system-attachments)
  :short "Extend the use of @(see linear-arithmetic) during rewriting"
  :long "<p>This topic concerns an advanced control for the ACL2 prover.</p>

 <p>This zero-ary attachable system function supports extending the usual use
 of @(see linear-arithmetic) during rewriting, specifically with the
 test (first) argument of a call of @('IF').  To get this additional power,
 possibly at considerable loss of efficiency, evaluate @('(defattach-system
 heavy-linear-p constant-t-function-arity-0)').  To restore the default
 behavior, evaluate @('(defattach-system heavy-linear-p
 constant-nil-function-arity-0)').</p>")
other
(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)
  Enabled:      T
  Hyps:         T
  Equiv:        EQUAL
  Lhs:          (PKG-IMPORTS "PKG0")
  Rhs:          '(A B)
  Backchain-limit-lst: NIL
  Subclass:     ABBREVIATION
  ACL2 !>
 })

 <p>Consider a @(tsee defpkg) event that is introduced during evaluation of an
 @(tsee include-book) event, where that @('include-book') event occurs @(see
 local)ly inside a surrounding @(tsee encapsulate) event or another
 @('include-book') event.  In that case, traces of the axiom added by the
 @('defpkg') event will disappear after the surrounding event is admitted.  If
 ACL2 were to allow the same package name to be defined subsequently with a
 different set of imports, that could cause inconsistencies.  See @(see
 package-reincarnation-import-restrictions) for relevant discussion, or see the
 &ldquo;Essay on Hidden Packages&rdquo; in source file @('axioms.lisp')..</p>

 <p>In order to prevent unsoundness, 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)).  This invariant guarantees that
 if you then try to define a package in a manner inconsistent with its earlier
 definition &mdash; specifically, with a different imports list &mdash; you
 will see an error because of the tracking discussed above.</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>")
other
(defxdoc hidden-defpkg
  :parents (packages defpkg)
  :short "Handling defpkg events that are local"
  :long "<p>See @(see hidden-death-package)</p>")
other
(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>Another common case, described below, is when @('hide') is added by the
 simplifier because an attempted execution of the term failed.  In this case,
 an @(':expand') hint as described above will have no effect because the
 execution will just fail again; the @('hide') will be re-inserted; and the
 hapless user will find themselves questioning their own sanity.</p>

 <p>@('Hide') terms are generally ignored not only by the rewriter but by other
 ACL2 procedures, including the induction heuristics and (by default) removal
 of @(see guard-holders).</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 1 2 3)') arises in a proof.  Since the
 arguments are all constants, ACL2 may 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.
 Often that expression will use a call of @(tsee comment), where @('(comment x
 y)') is logically just @('y'), to tell you the problematic constrained
 function, in this case by rewriting the original expression to the following;
 see @(see comment).  (Near the end of this topic we discuss how to avoid the
 call of @('comment').)</p>

 @({
 (hide (comment "Failed attempt to call constrained function CONSTRAINED-FN"
                (another-fn 1 2 3)))
 })

 <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 @('f')
 of no arguments in terms of a constrained function @('g'), you may
 often see @('(f)') rewrite to:</p>

 @({
 (hide (comment "Failed attempt to call constrained function G"
                (f))).
 })

 <p>We do not hide the term if the @(see executable-counterpart) of the
 function is @(see disable)d &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 (comment ".." (another-fn 1 2
 3)))') mentioned above.  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 (comment "Failed attempt to call constrained function CONSTRAINED-FN"
                          (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 a hint to @(':expand') that term.
 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 (comment "Failed attempt to call constrained function CONSTRAINED-FN"
                          (another-fn 1 2 3)))
           (constrained-fn 1 2 3))
    :hints
    (("Goal" :expand
             (hide (comment "Failed attempt to call constrained function CONSTRAINED-FN"
                            (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>

 <p>Finally, note that you can avoid the generation of @(tsee comment) calls
 inside the generated call of @('hide'), as was the case through ACL2 Version
 8.2, as follows.</p>

 @({
 (defattach-system ; generates (local (defattach ...))
   hide-with-comment-p
   constant-nil-function-arity-0)
 })

 <p>After evaluation of this event, our running example @('(another-fn 1 2 3)')
 would generate @('(hide (another-fn 1 2 3))') rather than a term of the
 form @('(hide (comment "..." (another-fn 1 2 3)))').</p>

 <p>In some cases such backward compatibility might also be achieved as
 follows; also see @(see guard-holders).</p>

 @({
 (defattach-system ; generates (local (defattach ...))
   remove-guard-holders-blocked-by-hide-p
   constant-nil-function-arity-0)
 })

 @(def hide)")
other
(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 (list (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 is described below.  In
 general it takes as its value a list of ``lemma instances'' (see @(see
 lemma-instance)), but it allows special cases, including a single lemma name.
 In each case, a goal @('G') is replaced by a new goal @('(IMPLIES P G)'),
 where @('P') is the theorem specified by the (conjunction of the) lemma
 instances provided.  Here are some examples.</p>

 @({
  ; Attach :use hint to the top-level goal G, which is named "Goal",
  ; replacing it by (implies P G) where P is the statement of lemma23:
  :hints (("Goal" :use lemma23))

  ; Equivalent to the above, using 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)).  Not documented in this topic are
 such hints implemented in books; for an example of so-called @(':consider')
 hints, see @(see consideration).</p>

 <p>When the ACL2 prover encounters a goal @('"G"'), then the first hint of
 the form @('("G" :kwd1 val1 ...)') is applied to that goal.  This usually
 means that all hints for the goal @('"G"') after the first such hint are
 ignored, and ACL2 produces a warning about that.  (Note however that
 @('("G")') is simply dropped; such an empty hint is considered not to be
 there, for purposes of this discussion.)  If there are default hints (see
 @(see set-default-hints)) then this behavior applies to the user-supplied list
 of @(':hints') followed by the default hints; see @(see
 hints-and-the-waterfall) for a detailed discussion of how hints fit into the
 ACL2 waterfall, which in particular has a &ldquo;slightly tricky
 example&rdquo; illustrating the unusual case when a goal can be encountered
 more than once, thus applying more than one hint on that goal.  Also see @(see
 override-hints) for an advanced feature that can modify the &ldquo;first
 hint&rdquo; behavior described above.  For examples of the sophisticated use
 of hints, primarily for experts, see community book
 @('books/hints/basic-tests.lisp').</p>

 <p>Duplicate hint keywords are prohibited in a hint; for example, the hint
 @('("Goal" :induct t :induct t)') is illegal.  Also, certain hint keywords
 are incompatible within a given hint, for example, in @('("Goal" :use
 nth :induct t)').  These restrictions for duplicates and compatibility apply
 not only for explicit hints but also for hints that are generated by computed
 hints or @(see override-hints); for example, the command
 @('(add-override-hints '((append '(:use nth :induct t) keyword-alist)))') will
 cause subsequent proof attempts to fail because @(':use') and @(':induct') are
 incompatible keywords.  Here is the full list of incompatibilities for hint
 keywords on a given goal.</p>

 <ul>

 <li>It is illegal to use two or more keywords from the following list, except
 that @(':use') and @(':cases') may be used together:<br/>
 @(`(cons :induct *top-hint-keywords*)`).</li>

 <li>It is illegal to use @(':reorder') with either @(':or') or
 @(':induct').</li>

 </ul>

 <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 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 @(see 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 @(see
 type-reasoning), 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 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-cl-proc-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><b>Remarks.</b></p>

 <p>(1) An @(':induct') hint is applied to a goal even if a @(':do-not-induct')
 hint is in effect for that goal.  Consider the following examples.</p>

 @({
 (thm (equal (append (append x y) z) (append x y z))
      :hints (("Goal" :induct t :do-not-induct t)))

 (thm (and (equal (append (append x y) z) (append x y z))
           (equal (append (append u v) w) (append u v w)))
      :hints (("Goal" :do-not-induct t)
              ("Subgoal 2" :induct t)))
 })

 <p>In the first of these, the @(':do-not-induct') hint has no effect on the
 proof; instead, the @(':induct') hint forces an induction that allows the
 proof to succeed (without any sub-inductions).  The second of these
 illustrates that even though @(':do-not-induct') can stop sub-inductions, its
 effect is overridden by @(':induct').  For the proof of that second example,
 ACL2 immediately splits into two subgoals.  Then in spite of the top-level
 @(':do-not-induct') hint, the proof is allowed to proceed past Subgoal 2,
 which requires induction, because of the hint @(':induct t').  However, the
 proof halts after Subgoal 1 because of the @(':do-not-induct') hint that has
 been established ``above'' it, at @('"Goal"').  (For more about the way
 hints are processed, see @(see hints-and-the-waterfall).)</p>

 <p>(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>: (0) Note that in the event that
 a @(':definition') rule has been admitted for @('fn'), then by default, the
 body @('b') is determined by the (most recently admitted such) rule rather
 than the original definition of @('fn'); see @(see definition).  (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 @(see definition) rule or (less often) @(tsee
 rewrite) rule 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 that is not an atom or a quoted
 constant.  The value @('t') indicates that the system use induction
 immediately by applying its induction heuristic to the specified goal
 (without trying simplification, etc.).  Otherwise, the system should apply
 induction immediately, but it should analyze @('value') rather than the goal
 to generate its @(see induction) scheme.  Either way (i.e., for value @('t')
 or not), 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>

 @({
   (list (nth i a) (nth j a))
 })

 <p>suggests simultaneous @(see induction) on @('i'), @('j'), and @('a').</p>

 <p>When the selected induction scheme is suggested by just one term the
 induction is announced with a message like ``@('We will induct according to a
 scheme suggested by')'' the term in question. But if several terms are
 involved in the suggestion, either because they suggested the same scheme or
 because their suggestions were merged with others to form the selected scheme,
 the announcement includes the phrase ``@('while accommodating')'' the other
 terms.  Furthermore, as noted in @(see induction-heuristics), the induction
 mechanism communicates to the simplifier, passing to it the list of all the
 terms being accommodated.  The simplifier preferentially expands those terms
 during the subsequent proof attempt.</p>

 <p>Thus, if the prover automatically selects an induction that accommodates
 terms besides the one suggesting and justifying the induction, and you want to
 give an @(':induct') hint that causes the same behavior, your hint should
 include the term suggesting the induction and all of the accommodated terms.
 We typically do this with a hint like @(':induct (list term0 term1
 ... termk)').</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 has no effect,
 although unlike an empty hint such as @('("Goal")'), it is not dropped.
 Thus, @('("Goal" :no-op t)') will shadow any later (or default) hint on
 @('"Goal"'), but @('("Goal")') will not.  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 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 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 the goal above.  Thanks!]

    ACL2 Warning [Use] in ( THM ...):  It is unusual to :USE the formula
    of an enabled :REWRITE or :DEFINITION rule, so you may want to consider
    disabling (:REWRITE CDR-CONS) in the hint provided for Subgoal D1.
    See :DOC using-enabled-rules.

    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>This hint, originally suggested by Bishop Brock, sometimes allows rules
 with free variables (see @(see free-variables)) to be applied successfully by
 the rewriter, thus avoiding the clutter, case-splitting, and theory management
 (disabling) that can occur with @(':use') hints.</p>

 <p>Warning: This is a sophisticated hint that may be most appropriate for
 experienced ACL2 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
 subst_1 subst_2 ...)'), 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 @('(subst_1 subst_2 ...)')
 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 <i>matching substitution</i>, @('s'), such that
 the instantiation of @('lhs') using @('s') is equal to that term.  If however
 the @(':restrict') hint contains @('(x subst_1 subst_2 ...)'), then this
 behavior will be modified by restricting @('s') so that it must extend
 @('subst_1'); and if there is no such @('s'), then @('s') is restricted so
 that it must extend @('subst_2'); and so on, until such @('s') is produced
 &mdash; or, the list of substitutions is exhausted without producing a
 matching substitution, in which case 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 subst_1 subst_2 ...)') is replaced by @('(rj subst_1
 subst_2 ...)') for each @('j').  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>The following example, supplied by Mihir Mehta, illustrates the use of
 @(':restrict') to handle free variables (in this case, a single free variable
 @('y')).  The call of @(tsee thm) below fails without the indicated
 @(':restrict') hint.</p>

 @({
  (defthm subsetp-trans
    (implies (and (subsetp x y) (subsetp y z)) (subsetp x z)))
  (defthm subsetp-evens (subsetp-equal (evens l) l))
  (thm (subsetp (evens (evens l)) l)
       :hints (("Goal" :restrict ((subsetp-trans ((y (evens l))))))))
 })

 <p>Here is another example, this one 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: that is, the @(':use') hint
 replaces a goal, @('G'), by the new goal, @('(IMPLIES P G)'), where @('P') is
 the theorem specified by the (conjunction of the) lemma instances provided.
 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') (documented above).  Sometimes @(see
 theories) are helpful when employing @(':use') hints; see @(see
 minimal-theory).</p>

 <p>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>")
other
(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''.  Then, we describe how hints are
 handled by the waterfall.</p>

 <p><b>The Waterfall.</b></p>

 <p>The ACL2 <i>waterfall</i> is the heart of the ACL2 prover.  It attempts to
 prove a given goal and either completes the proof, fails, or produces goals to
 be proved by induction or forcing rounds.  The waterfall comprises a series of
 <i>steps</i>, such as simplification or generalization, each of which attempts
 to replace a given goal by zero or more subgoals whose provability implies
 provability of that goal.  Note that every proof by induction starts a new
 trip through the waterfall, as does every forcing round; and these occur only
 after all preceding trips through the waterfall are complete.  Let us see in
 more detail how the waterfall works.</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)); that is followed by the main ACL2
 simplifier and then the &ldquo;settled-down&rdquo; process described further
 below; 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''.  This notion of ``settled down'' is
 handled, as follows, by the next waterfall process after simplification: the
 ``settled-down'' process.  If some ancestor of the goal (possibly the goal
 itself) has previously settled down, then the ``settled-down'' process is
 deemed to have missed on the goal.  Otherwise it hits 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, suppose that
 @('"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 it does not hit not on any of its children or their
 children (and so on), because each of those has an ancestor, @('"Subgoal
 2.3"'), that has already been marked as ``settled-down''.</p>

 <p>The next proof process after settled-down 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 !>(set-gag-mode nil)
 <state>
 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, consider
  combining them into a single hint of the form ("Goal" :kwd1 val1 :kwd2
  val2 ...). See :DOC hints and :DOC hints-and-the-waterfall; community
  book books/hints/merge-hint.lisp might also be helpful.

  [Note:  A hint was supplied for the goal above.  Thanks!]

  [Note:  A hint was supplied for 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 first because user-supplied hints are ahead
 of default hints in the list of pending hints; we then get the first
 &ldquo;Note&rdquo; 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 &ldquo;settled-down&rdquo;
 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
 &ldquo;Note&rdquo; 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>")
other
(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 commands executed so far.  For example, you can ask to see the
 most recently executed command (by issuing @(':')@(tsee pc) @(':x')), or the
 preceding 10 commands (by issuing @(':')@(tsee pbt) @(':x-10')), or the
 command that introduced a given function symbol, @('fn') (by issuing @(':pc
 fn')).  You can also undo back through some previous command (see @(see ubt)),
 restoring the logical @(see world) to what it was before the given
 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
 commands.  You must understand these terms to use the commands.  These terms
 are documented with @(see documentation) entries of their own.  See @(see
 command), see @(see events), see @(see command-descriptor), and see @(see
 logical-name).</p>")
other
(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)")
other
(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)")
other
(defxdoc hons-acons!
  :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!)")
other
(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>")
other
(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)")
other
(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)")
other
(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>")
other
(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)")
other
(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)")
other
(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>")
other
(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)")
other
(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)")
other
(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.  Otherwise
 @('hons-get') simply invokes @(tsee hons-assoc-equal), which is similar (in
 definition and in performance) to @(tsee assoc-equal), on @('key') and
 @('alist').</p>

 @(def hons-get)")
other
(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>")
other
(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>")
other
(defxdoc hons-shrink-alist
  :parents (fast-alist-fork acl2-built-ins)
  :short "Deprecated feature"
  :long "<p>Deprecated.  Alias for @(tsee fast-alist-fork).</p>")
other
(defxdoc hons-shrink-alist!
  :parents (fast-alist-fork! acl2-built-ins)
  :short "Deprecated feature"
  :long "<p>Deprecated.  Alias for @(tsee fast-alist-fork!).</p>")
other
(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)")
other
(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)")
other
(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>")
other
(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>")
other
(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>")
other
(defxdoc how-to-contribute
  :parents (about-acl2 community)
  :short "Guide to contributing code to ACL2."
  :long "<p>The main way to contribute code to ACL2 is to open a pull request
 (PR) to the <a href='https://github.com/acl2/acl2'>ACL2 GitHub
 repository</a>.  First create a personal fork of the
 repository and commit your changes/additions there.  Then open a
 PR to merge your changes into the main ACL2 repository.  Please ensure
 your PR follows these guidelines:</p>

 <h3>Required: Make Changes Only Within the @('books/') Directory</h3>

 <p>While the community is invited to submit contributions to the <see
 topic='@(url community-books)'>Community Books</see>, source files outside of
 the @('books/') directory should not be modified, except by system
 maintainers.</p>

 <p>Suggestions for system changes can be emailed to <a
 href='mailto:kaufmann@cs.utexas.edu'>Matt Kaufmann</a>. (Prospective system
 developers should see the @(see developers-guide).)</p>

 <p>New developments that do not clearly belong in an existing directory
 are often put into the @(tsee projects) subdirectory of @('books/').</p>

 <h3>Required: Avoid Problematic Constructs</h3>

 <p>Avoid introducing code that may fail on machines/environments
  other than your own.  In particular, avoid the following:</p>

         <ul>

         <li>Dependence on any files not included in your PR.  In particular,
         any book that depends on an external tool, such as an SMT solver,
         should include an appropriate <see topic='@(url
         build::cert_param)'>cert_param</see>.</li>

         <li>Dependence on environment variables that will not be set in other
         users' environments.</li>

         <li>Use of absolute pathnames (e.g., mentions of your home directory).
         These are likely to cause problems for other users.  To bring in other
         Community Books, use the @(':dir :system') option of @(tsee
         include-book).</li>

         <li>Constructs with timeouts that cause proof attempts to be aborted
         after a short time.  These may cause failures on slower or heavily
         loaded machines.</li>

         </ul>

 <h3>Required: Check the Build</h3>

 <p>Before making your PR, you should run a regression to ensure that
 your changes/additions do not break the build. To do so, run the following
 @('make') command in the ``books'' directory:</p>

 @({
   make -j 8 regression
 })

 <p>(Note: the @('-j 8') option in the above command is only illustrative. It
 instructs @('make') to use 8 hardware threads. You may use a higher or lower
 number to align with your system. See @(see books-certification) for an
 extended discussion on community book certification.)</p>

 <h3>Required: Change the Base Branch of your PR to @('testing')</h3>

 <p>When opening your PR to merge changes into the main ACL2 repository, set
 the base branch to the @('testing') branch (or similar) (<i>not</i> the
 @('master') branch).  Once your PR is accepted into the @('testing') branch,
 it will be tested and merged automatically into the @('master') branch if all
 tests pass.</p>

 <h3>Suggested: Follow Best Practices for ACL2 Code</h3>

 <p>See @(see best-practices) for recommended code practices.</p>

 <h3>Suggested: Document Your New Books</h3>

 <p>Consider creating documentation using the @(tsee xdoc) system.  Then, to
 ensure your new topics appear in the manual, ensure they are included by
 @('books/doc/top.lisp'), perhaps via another book that it includes, such as
 @('books/projects/top-doc.lisp').</p>

 <h3>Suggested: Update the Release Notes</h3>

 <p>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').</p>

 <h3>Resources for Git/GitHub</h3>

 <p>For those new to Git (the version control system) or GitHub (the platform
 on which the ACL2 Git repository is hosted), see @(see git-quick-start).</p>

 <h3>Frequent Contributors</h3>

 <p>Frequent contributors may request to join the <a
 href='https://github.com/acl2/acl2'>ACL2 GitHub project</a>. Such contributors may
 push directly to various testing branches without opening a PR (although it is
 still good practice to open a PR when modifying a widely used book or one
 primarily authored by someone else).</p>

 <p>To request to join the project, email one of the following
 individuals:</p>
 <ul>
   <li>Eric Smith (@('eric.smith@kestrel.edu'))</li>
   <li>David Rager (@('ragerdl@gmail.com'))</li>
   <li>Sol Swords (@('sswords@gmail.com'))</li>
 </ul>

 <p>See also the @(see community) topic for other ways to connect with the ACL2
 community, and ways to get help.</p>")
other
(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>")
other
(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>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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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)")
other
(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>")
other
(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>")
other
(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)")
other
(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)")
other
(defxdoc ignored-attachment
  :parents (defattach defconst defmacro defpkg)
  :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)))
 })")
other
(defxdoc ilk
  :parents (apply$)
  :short "Indicator of how an argument is used"
  :long "<p>The <i>ilk</i> of the ith argument of a @(tsee badge)d function
  symbol @('fn') is one of three tokens with the following meanings.</p>

  <ul>

  <li>@(':FN') - the ith argument is used exclusively as a function object by
  @('fn'); informally this means that the argument is passed only into slots of
  ilk @(':FN') in the definition of @('fn') and that on some (syntactic)
  execution paths reaches the first argument of a call of @(tsee apply$).</li>

  <li>@(':EXPR') - the ith argument is used exclusively as a expression object
  by @('fn'); informally this means that the argument is passed only into slots
  of ilk @(':EXPR') in the definition of @('fn') and that on some (syntactic)
  execution paths reaches the first argument of a call of @(tsee ev$).</li>

  <li>@('NIL') - the ith argument is never used as a function or expression
  object in the definition of @('fn').</li>

  </ul>

  <p>See @(tsee badge) for more details.</p>

  <p>The <i>ilks</i> of all the arguments of @('fn') are stored in the @(tsee
  badge) of @('fn').  If each ilk of @('fn') is @('NIL') the @(tsee badge)
  stores a @('T') as the ``list'' of ilks.</p>

  <p>The @(tsee badge) of @('fn') is computed by a successful call of @(tsee
  defwarrant) on @('fn').</p>

  <p>Ilks are used by the various notions of @(see tame)ness controlling
  whether @(tsee apply$) and @(tsee ev$) can properly interpret a quoted
  function or expression object.</p>")
other
(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)")
other
(defxdoc illegal-state
  :parents (defabsstobj)
  :short "Illegal ACL2 state"
  :long "<p>See @(see set-absstobj-debug) for background on invariance
 violations for abstract @(see stobj)s.  In short, they may occur when
 execution does not complete for certain atomic operations.</p>

 <p>Such violations cause the following error message to be printed.</p>

 @({
 ACL2 Error in CHK-ABSSTOBJ-INVARIANTS:  Possible invariance violation
 for an abstract stobj!
 **PROCEED AT YOUR OWN RISK.**
 To proceed, evaluate the following form.
 :CONTINUE-FROM-ILLEGAL-STATE
 See :DOC set-absstobj-debug.
 })

 <p>At this point, the only way to get ACL2 to evaluate further input is to
 submit the form @(':CONTINUE-FROM-ILLEGAL-STATE'), as noted above &mdash; or
 more generally, the form it actually represents,
 @('(CONTINUE-FROM-ILLEGAL-STATE)'), which may need to be written as
 @('(ACL2::CONTINUE-FROM-ILLEGAL-STATE)') if the @(tsee current-package) is
 other than @('"ACL2"').  There is actually one exception: @(':')@(tsee q) is
 accepted, to pop out of the current call of @(tsee ld).</p>

 <p>To get a bit more information from the error message displayed above, see
 @(see set-absstobj-debug).</p>

 <p>See @(see community-book) file
 @('books/system/tests/abstract-stobj-nesting/nested-abstract-stobjs-input.lsp'),
 Examples 3 and 4, for relevant examples.</p>

 <p>Technical note.  An illegal-state is entered when ACL2 sets the @('ld')
 special, @(tsee ld-pre-eval-print), to the value @(':illegal-state').</p>")
other
(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)
 })")
other
(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>")
other
(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)")
other
(defxdoc improper-consp
  :parents (lists acl2-built-ins)
  :short "Recognizer for improper (non-@('nil')-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)")
other
(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>")
other
(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>")
other
(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
 })")
other
(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>")
other
(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)

  ; Include a project book:
  (include-book "my-subdir/my-book" :dir :my-project)

  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 without the @('".lisp"') extension.  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 @(see pathname) for a directory, 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
 the given @('file') using the @('books/') directory of your ACL2 installation;
 see ``Books Directory'' below.  To define other keywords that can be used with
 @(':dir'), see @(see add-include-book-dir), @(see add-include-book-dir!), and
 @(see project-dir-alist).  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 t)') has been evaluated; see @(see
 set-guard-checking).  If you want to run with different guard-checking,
 consider using @('ld') instead, or in addition; see @(see ld).</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).  If those books reside
 elsewhere, the environment variable @('ACL2_SYSTEM_BOOKS') can be set to the
 directory under which they reside.  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 @(see installation) instructions, these
 books will be the ACL2 community books; see @(see community-books).  For
 another way to set the system books directory, which also permits similar
 handling for other directories, see @(see project-dir-alist).</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>")
other
(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 arguments are indeed runes, not merely having the shapes of runes.</p>")
other
(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>")
other
(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 recursively defined
 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 definition suggests a dual induction scheme that ``unwinds''
 the function from a given application.  The case analysis in the induction
 scheme suggested by a function call is determined by the case analysis used to
 prove termination.  That case analysis chooses a subset of the tests governing
 recursive calls and then generates base cases for the combinations of tests
 that do not lead to recursive calls and induction steps for the combinations
 that do.  See @(see rulers) and @(see induction-coarse-v-fine-grained).</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 cons, the induction scheme suggested by
 @('(append x y)') has a base case supposing @('x') to be an atom (i.e., not a
 cons) 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 @(see induction-heuristics).</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 (with an exception for induction schemes
 by way of user-defined induction rules, as discussed at the end below).  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 @(see 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') has a recursive
 definition, then the definition's dual induction scheme is suggested (i.e.,
 unwinding the function).</p>

 <p>(Remark.  Unlike @(':induct') @(see hints), the @(':scheme') of an
 @(':induction') rule only introduces induction schemes based on the top-level
 function symbol of the indicated term, not of any of its subterms.  End of
 Remark.)</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 natural number
 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 less
 than or equal to @('1').  In the base case we must prove @('(:p i)') without
 further help.  The induction step deals with those natural numbers @('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 @(see
 rune) is @(see disable)d the heuristic link between @('pat-term') and
 @('scheme-term') is broken.</p>

 <p>Note that if @('fn') is defined recursively and @('(:induction fn)') is
 @(see disable)d, then normally the induction scheme for @('fn') will not be
 available during a proof.  However, the induction scheme for @('fn') is
 available, even if it is disabled, when it is indicated by application of a
 user-defined @(':induction') rule.  So for the @(':induction') rule above,
 @('recursion-by-sub2-induction-rule'): even if @('(:induction
 recursion-by-sub2)') is disabled, nevertheless the induction scheme for
 @('recursion-by-sub2') will be available to apply to the instantiated
 @(':scheme-term').</p>")
other
(defxdoc induction-coarse-v-fine-grained
  :parents (rulers)
  :short "advice on case explosion in complex inductions"
  :long "<p>Recursive functions suggest inductions based on the case analysis
  in the function definition and the positions of recursive calls within that
  case analysis.  That analysis is done when termination is proved.  Key parts
  of that analysis are the notions of governing tests and ruling tests.  By
  using the so-called ``ruler-extenders'' feature of termination analysis you
  can sometimes choose between ``coarse-grained'' and ``fine-grained''
  inductions.  The former have few cases but may provide multiple and sometimes
  irrelevant induction hypotheses.  The latter provide more cases, each
  targeted at a given output, and tend to provide only induction hypotheses
  needed for that output.  See @(see rulers) for a discussion of
  ruler-extenders.</p>

  <h3>Governing versus Ruling Tests</h3>

  <p>Roughly speaking, a test <i>governs</i> a recursive call if the test must
  be true for control to reach that call.  The <i>ruling</i> tests are a subset
  of the governing tests and are the ones that determine the case analysis of
  any suggested induction.</p>

  <p>For example, if we are analyzing a definition of @('(fn x)') and the body
  is @('(if (not (consp x)) (h nil) (h (fn (cdr x))))') then @('(consp x)')
  governs the recursive call and it also rules the call.  But if the body were
  @('(h (if (not (consp x)) nil (fn (cdr x))))') then @('(consp x)') governs the
  recursive call but may not rule it.  It would be considered a ruler if the
  symbol @('h') were on the ``ruler-extenders'' list &mdash; the list of
  symbols that allow further collection of rulers from inside terms that begin
  with those symbols.</p>

  <p>The default setting of ruler-extenders is @('(if mv-list return-last)').
  That means that termination (and induction) analysis stops looking for ruling
  tests when a term is encountered that does not begin with one of these listed
  symbols.  For example, under the default ruler-extenders, when the analysis
  encounters a term that starts with a @('lambda') expression, that term is
  considered a tip of the tree.  (@('Lambda') expressions are relevant because
  they are introduced by the macroexpansion of @(tsee let) and @(tsee let*)
  expressions, which arise frequently in interesting recursive functions
  because they facilitate <i>code sharing</i> by allowing the computation of
  intermediate results used on multiple output branches.)  When the analysis
  encounters a term considered a tip, the rulers collected so far are used to
  rule <i>all</i> the recursive calls in that tip.  So at a tip, the analysis
  collects all the recursive calls occurring in that tip and forms measure
  conjectures and, eventually, induction hypotheses about them, using the
  rulers as the hypotheses of those conjectures.</p>

  <p>So the user can influence the determination of the rulers by setting the
  ``ruler-extenders'' in effect when the function is admitted.  The global
  default ruler-extenders can be set by the event @('set-ruler-extenders') or
  specified locally in a @('defun') by the @(tsee xargs) keyword
  @(':ruler-extenders').  See @(see rulers) for the details.</p>

  <h3>Coarse versus Fine Induction Case Analysis</h3>

  <p>Most often, users think about ruler-extenders only in the context of
  <i>failed</i> termination proofs: inspection of the measure conjectures
  reveal that an important governing hypothesis was curiously omitted, the user
  consults the documentation or appeals for help from other users, and is
  reminded of ruler-extenders.  One could argue that users forget about
  ruler-extenders because the default setting for ruler-extenders is so often
  the ``right'' one.  But sometimes even a function that is successfully
  admitted under the default setting would benefit from selecting a non-default
  setting for ruler-extenders.</p>

  <p>Sometimes you may feel that the prover is struggling with an induction
  suggested by a function, even though the function that suggested the
  induction is the one you expected to be selected, and for most simple
  recursive functions the induction suggested is the ``perfect'' induction for
  that function.  This problem of the prover struggling to simplify the
  induction steps might arise most commonly with functions that have @(tsee
  let*) bindings that contain @('if')-expressions, some of which contain
  recursive calls.  For example, the following artificial example raises the
  possibility of this problem.</p>

  @({
  (defun fn (x y)
    (if (consp x)
        (let* ((y1 (if (consp (car x))
                       (fn (car x) (cons 'car y))
                       y))
               (y2 (if (consp (cdr x))
                       (fn (cdr x) (cons 'cdr y1))
                       y1)))
          (cons y1 y2))
        y))
  })

  <p>Recall that @('let*') expressions are translated into nested @('lambda')
  expressions, so the formal definition of @('fn') is</p>

  @({
  (defun fn (x y)
    (if (consp x)
        ((lambda (y1 x)
           ((lambda (y2 y1) (cons y1 y2))
            (if (consp (cdr x))
                (fn (cdr x) (cons 'cdr y1))
              y1)
            y1))
         (if (consp (car x))
             (fn (car x) (cons 'car y))
           y)
         x)
        y))
  })

  <p>So, the entire @('let*') above, i.e., the formal term starting with the
  first @('lambda') expression, is a tip ruled only by @('(consp x)').  The
  @('if')s within it are not considered even though their tests govern (but do
  not rule) the subsequent recursions.  The recursive calls in that tip are</p>

  @({
  (fn (car x) (cons 'car y))
  })

  <p>and</p>

  @({
  (fn (cdr x)
      (cons 'cdr
            (if (consp (car x))
                (fn (car x) (cons 'car y))
                y))).
  })

  <p>The default measure in this definition is @('(acl2-count x)').  The
  measure conjectures are easy to prove because @('(consp x)') implies
  @('(acl2-count (car x))') and @('(acl2-count (cdr x))') are both less than
  @('(acl2-count x)').  Since there are no more recursive calls in the
  definition, @('fn') is admitted.</p>

  <p>Now consider how the prover would attempt to prove @('(p (fn x y))') by
  the induction suggested by @('fn').  The induction argument, shown below, has
  one base case and one induction step.  The induction step has two induction
  hypotheses.</p>

  @({
  (and (implies (not (consp x)) (p (fn x y)))
       (implies (and (consp x)
                     (p (fn (car x) (cons 'car y)))
                     (p (fn (cdr x)
                            (cons 'cdr
                                  (if (consp (car x))
                                      (fn (car x) (cons 'car y))
                                      y)))))
                (p (fn x y)))).
  })

  <p><b>Note</b>: Here and throughout this documentation topic we freely
  rearrange the formulas we display to make it easier to compare different
  induction schemes.  For example, when the prover attempts to prove @('(p (fn
  x y))') it lists the conjuncts above in the opposite order, i.e., the base
  case occurs last.  It can be hard to compare induction schemes from similar
  functions because ACL2's methods of generating induction schemes does not
  preserve the order of tips.</p>

  <p>The prover attempts to reduce each of these two conjuncts to @('T') by
  simplification.  The base case is generally simple.  So consider the
  induction step, the second implication above, which we abbreviate here as</p>

  <code>
  (implies (and (consp x)
                <i>ind-hyp1</i>
                <i>ind-hyp2</i>)
           <i>ind-concl</i>)
  </code>

  <p>where, <i>ind-hyp1</i>, the first induction hypothesis, is @('(p (fn (car
  x) (cons 'car y)))'), etc.  See @(see introduction-to-the-theorem-prover) for
  more details of how the rewriter works.  When rewriting the formula above it
  basically proceeds left-to-right, innermost first, keeping track of what can
  be assumed given the context in which terms occur.  Thus, by the time the
  rewriter gets to the induction conclusion, <i>ind-concl</i>, the two
  induction hypotheses will have been rewritten, making them easier to find and
  identify as true if they occur in the rewriting of the conclusion.</p>

  <p>But rewriting <i>ind-hyp1</i> here will involve rewriting @('(fn (car
  x) (cons 'car y))'), which is completely irrelevant to half of the proof of
  <i>ind-concl</i>.  In particular, inspection of @('fn') reveals that the
  first recursive call of @('fn') is only relevant if @('(consp (car x))') is
  true.  But we know nothing about @('(car x)') in this induction step.
  Furthermore, rewriting a call of a recursive function can be very expensive
  since it requires (a) rewriting the actual expressions, then (b) rewriting
  the body of the function under a substitution replacing the function's
  formals by the rewritten actuals, and then (c) heuristically deciding whether
  the rewritten body is preferable to the call, given the subterms occurring
  elsewhere in the goal.</p>

  <p>Another way to describe the unfortunate induction scheme above is that it
  ``coarse,'' because it provides a simple case analysis, which necessitates
  lumping all the possibly relevant induction hypotheses into a single case (in
  this particular example).  When the induction conclusion opens, after the
  induction hypotheses have all been simplified, it will cause further
  splitting, (e.g., on @('(consp (car x))')), and in some of those subgoals
  some of the simplified induction hypotheses will be irrelevant (but still
  burden the simplification process if the cases are not proved
  immediately).</p>

  <p>Depending on how hard it is to rewrite irrelevant induction hypotheses
  &mdash; which depends not just on the function, like @('fn'), suggesting the
  induction but also on the conjecture being proved &mdash; it might be more
  efficient to have a finer-grained case analysis so that the only induction
  hypotheses in a given case are those on a given execution path.</p>

  <p>A finer-grained induction scheme is generated, in the case of @('fn'), by
  arranging for @('lambda') expressions <i>not</i> to stop the collection of
  rulers.  This can be done by adding the keyword @(':lambdas') to the
  ruler-extenders.  The presence of that keyword means ``keep collecting rulers
  as you dive into <i>any</i> term beginning with a @('lambda') expression.''
  (By the way, normally @(':ruler-extenders') expects a list but if you specify
  the single keyword @(':lambdas') it denotes the list @('(if :lambdas mv-list
  return-last)').)  Again, see @('rulers') for details.</p>

  <p>If we had defined @('fn') as shown below we would get the finer induction
  analysis shown subsequently.</p>

  @({
  (defun fn (x y)
    (declare (xargs :ruler-extenders :lambdas))
    (if (consp x)
        (let* ((y1 (if (consp (car x))
                       (fn (car x) (cons 'car y))
                       y))
               (y2 (if (consp (cdr x))
                       (fn (cdr x) (cons 'cdr y1))
                       y1)))
          (cons y1 y2))
        y))
  })

  <p>Note that @('fn') can be admitted without extending the rulers &mdash; we
  have already demonstrated that.  We are including @(':lambdas') here
  precisely to get a finer case analysis for induction.</p>

  <p>The induction generated is shown below.  We have slightly simplified the
  induction by replacing @('(if ')<i>a b c</i>@(')') by <i>b</i> when <i>a</i>
  is among the hypotheses in the case analysis, and by replacing @('(if ')<i>a
  b c</i>@(')') by <i>c</i> when @('(not ')<i>a</i>@(')') is among the
  hypotheses.  This simplification is actually not done by induction analysis
  but by the first simplification.</p>

  @({
  (and (implies (not (consp x)) (p (fn x y)))
       (implies (and (consp x)
                     (not (consp (car x)))
                     (not (consp (cdr x))))
                (p (fn x y)))
       (implies (and (consp x)
                     (not (consp (car x)))
                     (consp (cdr x))
                     (p (fn (cdr x) (cons 'cdr y))))
                (p (fn x y)))
       (implies (and (consp x)
                     (consp (car x))
                     (not (consp (cdr x)))
                     (p (fn (car x) (cons 'car y))))
                (p (fn x y)))
       (implies (and (consp x)
                     (consp (car x))
                     (consp (cdr x))
                     (p (fn (car x) (cons 'car y)))
                     (p (fn (cdr x)
                            (cons 'cdr (fn (car x) (cons 'car y))))))
                (p (fn x y))))
  })

  <p>Note that the case analysis here steers the @('(fn x y)') in the
  conclusion down exactly one path and the only hypotheses provided in each
  induction step concern recursive calls on that path.</p>

  <p>The finer case analysis gives us two base cases and four induction steps,
  one of which has two induction hypotheses.  We'll encounter terms of the form
  @('(p (fn ...))') nine times in using this scheme, instead of just four such
  terms in the first scheme we showed.  It may seem surprising that this scheme
  ever leads to faster proofs than the earlier one.  But it can.  Whether it
  does depends, as mentioned above, on the complexity of rewriting the
  recursive calls involved and the conjecture being proved.</p>

  <p><b>Note</b>: The ruler-extenders may include arbitrary function symbols
  and the keyword @(':lambdas') as above.  But it can also be set to @(':all')
  which makes all the governors be rulers, i.e., collection of rulers dives
  through all function symbols.  We focus here on diving through @('lambda')
  expressions because they are by far the most common ``function
  symbol'' (other than @('if')) under which one finds additional tests and
  recursive calls.</p>

  <p>In the next section we'll discuss a theorem that makes use of these
  insights and demonstrates that the finer scheme can lead to faster
  proofs.</p>

  <h3>An Actual Example of Coarse versus Fine Induction Schemes</h3>

  <p>The ACL2 prettyprinter is implemented with the function @('ppr').  It is
  basically the composition of two functions, @('ppr1'), which takes the object
  to be printed and computes a ``ppr tuple'' describing how much to indent each
  subexpression and where to break the lines, and @('ppr2'), which actually
  prints.  To admit @('ppr') as a logic mode function we have to prove
  termination and verify the guards of all the functions involved.  To verify
  the guards, we have to prove that @('ppr1') returns a @('ppr-tuple-p').  You
  can see the definitions of @('ppr1') and @('ppr-tuple-p') and their mutually
  recursive peers by using the @(':')@(tsee pe) command, e.g., @(':pe
  ppr1').</p>

  <p>We'll focus here on @('ppr1'), which is mutually recursive with
  @('ppr1-lst').  To prove anything interesting about a function in a mutually
  recursive clique you generally have to simultaneously prove analogous
  theorems about every function in the clique.  That is most often done by
  defining a ``flagged'' function which can recur as any function in the clique
  according to a flag.  The community book @('books/tools/flag') provides a
  convenient way to do that.  Since that book facilitates the introduction of
  the flagged function, it allows the generated definition to be processed with a
  user-supplied ruler-extenders.</p>

  <p>A good demonstration of the ``coarse'' and ``fine'' induction schemes for
  @('ppr1') can be found in the community book
  @('books/demos/ppr1-experiments').  We summarize the contents of that book
  here.</p>

  <p>The book proves that @('ppr1') returns a @('ppr-tuple-p') and
  @('ppr1-lst') returns a @('ppr-tuple-lst-p').  In fact, it does that proof
  seven times, under coarse and fine inductions and variations on some hints.
  The coarse induction is obtained by admitting a flagged version of
  @('ppr1')/@('ppr1-lst') under the default ruler-extenders.  The fine
  induction is obtained by admitting a differently named flagged version of
  @('ppr1')/@('ppr1-lst') with @(':ruler-extenders :lambdas').</p>

  <p>The coarse induction, generated under the default ruler-extenders, has 76
  cases.  Six are base cases.  The other 70 are induction steps with varying
  numbers of induction hypotheses as given in the sketch below.</p>

  @({
  (76           ;; 76 cases in the induction scheme
      (0 . 6)   ;; no induction hyps in 6 cases, i.e., Base Cases
      (1 . 8)   ;; 1 induction hyp in 8 cases
      (2 . 2)   ;; 2 induction hyps in 2 cases
      (3 . 16)  ;; 3 induction hyps in 16 cases
      (4 . 32)  ;; 4 induction hyps in 32 cases
      (8 . 4)   ;; 8 induction hyps in 4 cases
      (9 . 8))  ;; 9 induction hyps in 8 cases
  })

  <p>The fine induction, generated under the @(':lambdas') ruler-extension, can
  be similarly sketched.</p>

  @({
  (256          ;; 256 cases in the induction scheme
      (0 . 6)   ;; no induction hyps in 6 cases, i.e., Base Cases
      (1 . 8)   ;; 1 induction hyp in 8 cases
      (2 . 82)  ;; 2 induction hyps in 82 cases
      (3 . 80)  ;; 3 induction hyps in 80 cases
      (4 . 80)) ;; 4 induction hyps in 80 cases
  })

  <p>The induction generated under the @(':all') ruler-extensions is identical
  to the fine induction for @('ppr1') and @('ppr1-lst').  (No governing
  @('if')s are hidden under function calls other than @('if') and @('lambda')
  expressions in those two functions.)</p>

  <p>Regardless of which induction scheme we use, the proof that @('ppr1')
  returns a @('ppr-tuple-p') and that @('ppr1-lst') returns a
  @('ppr1-tuple-lst-p') fails without a certain hint: we have to tell the
  prover to expand the calls of @('ppr1') and @('ppr1-lst') in the conclusions
  of the induction steps.  If you try to prove the theorem without the hint the
  first checkpoint makes clear that you need the hint.  (This is not an
  uncommon problem in inductive proofs about mutually recursive functions.)
  But in the most basic like-for-like comparison of the successful proof of the
  theorem by each induction scheme augmented by an @(':expand') hint, the
  coarse induction takes 2,165 seconds and the fine induction takes 65 seconds.
  See scenarios 1 and 3 in the next section.</p>

  <h3>Comparing Several Optimizations</h3>

  <p>After noticing the performance differences between the coarse and fine
  inductions we spent some time trying to further optimize the proof.  We
  compared seven different combinations of approaches.  We discuss them here.
  See the @('books/demos/ppr1-experiments') for the details of each hint, etc.
  The times reported below were originally recovered from the @('.cert.out')
  file after certification of the book in September, 2023, using the
  development copy of ACL2 slated to become Version  8.6, running in CCL on a
  Macbook Pro.  Inspect the @('.cert.out') file for more recent results.</p>

  <p>As mentioned previously, a common situation with inductive proofs about
  complicated mutually recursive functions is that the calls in the conclusion
  aren't always automatically opened by ACL2's heuristics.  So it is not
  unusual in such proofs to provide a hint that explicitly expands the
  @('ppr1') and @('ppr1-lst') calls in the conclusion.  In these experiments we
  provide that hint two ways, either as part of fairly sophisticated computed
  hint or with an @(':expand') hint on @('"Goal"').  If you try to prove this
  theorem with no hint it fails.</p>

  <p>We will also be experimenting with the enabled status of @('ppr1') and
  @('ppr1-lst').</p>

  <p>The seven scenarios are specified by saying which induction scheme is
  used, whether @('ppr1') and @('ppr1-lst') are enabled or disabled by default,
  and what hints are provided.  There are three basic hints to chose from.</p>

  <ul>

  <li>@('computed') &mdash; when a subgoal becomes stable, open @('ppr1') and
      @('ppr1-lst') in the conclusion, and when any subgoal of that becomes
      stable again, enable @('ppr1') and @('ppr1-lst') and let ACL2's
      heuristics take over.  This hint only makes sense if @('ppr1') and
      @('ppr1-lst') are initially disabled.</li>

  <li> @('computed'') &mdash; like @('computed') but skips the first stable
       opening of @('ppr1') and @('ppr1-lst').  That is handled instead by an
       @(':expand') hint.</li>

  <li>@(':expand') &mdash; a traditional @(':expand') hint to open @('ppr1')
      and @('ppr1-lst') terms as they appear in induction conclusions.
      The expand hint is
      @({
      :expand
      ((:free (print-base print-radix width rpc state eviscp)
              (ppr1 x print-base print-radix width rpc state eviscp))
       (:free (print-base print-radix width rpc pair-keywords-p state eviscp)
              (ppr1-lst lst print-base print-radix width rpc
                        pair-keywords-p state eviscp)))
      })
      which allows the non-controller arguments of @('ppr1') and @('ppr1-lst')
      to be any terms but insists that the controllers, @('x') and @('lst'),
      respectively, be those particular variable names.</li>

      </ul>

  <p>In addition, we sometimes avail ourselves of special-purpose lemmas.</p>

  <ul>
  <li>@('NIL lem')  &mdash; rewrites @('(ppr1-lst nil ...)') to @('nil').</li>

  <li>@('MAX hack') &mdash; lemmas about @('MAX') allowing us to disable @('MAX')</li>
  </ul>

  <p>We try seven different combinations, numbered 1-7, but listed below
  in descending order of proof times.</p>

  @({
  n      induction    status                 hints               proof time

  1       coarse      enabled      :expand                         2165.19
  2       coarse      disabled     computed                         207.49
  6       fine        disabled     computed                          82.29
  3       fine        enabled      :expand                           65.00
  4       fine        disabled     computed + :expand                62.86
  5       fine        disabled     computed' + :expand + NIL lem     61.58
  7       fine        disabled     computed + :expand + MAX hack     55.14
  })

  <p>Note that scenarios 1 and 3 are a direct comparison of coarse and fine
  induction with exactly the same hint.  The coarse induction took 2165.19
  seconds and the fine induction took 65.00, despite the fact that the coarse
  induction had 76 cases to deal with and the fine induction had 256.  The most
  likely reason the coarse induction performed poorly is that there were 8
  induction steps that had 9 induction hypotheses each, even though no case
  ever actually required more than 4 induction hypotheses.</p>

  <p>Scenario 2 shows that much time is saved by disabling @('ppr1') and
  @('ppr1-lst') and expanding them (when stable) with the computed hint.  Note
  that since the computed hint first expands them in the conclusion and lets
  the resulting subgoals stabilize before enabling @('ppr1') and @('ppr1-lst'),
  the calls of @('ppr1') and @('ppr1-lst') in the induction hypotheses do not
  expand until the relevant case analysis is exposed by expanding the
  conclusion.</p>

  <p>Scenarios 4, 5, 6, and 7, attempt to improve upon the time seen in
  scenario 3.  We see that the best performance in this particular problem is
  to use the fine induction case analysis, keep the relevant recursive
  functions disabled by default, use an @(':expand') hint to open them in the
  conclusion but also have a computed hint that expands them in the conclusions
  if a stable subgoal arises, and only enable those functions if they're still
  in the subsequently stable subgoals.  The @('MAX hack') saves another 10% by
  avoiding case splits caused by the many occurrences of @('MAX') in
  @('ppr1').</p>

  <p>However, it should be noted that the major source of improvement is the
  use of the fine induction scheme.  The fact that there is only a 10% further
  improvement achieved by the various other hints suggests it may not be worth
  the effort!  Coding the computed hint took time and thought, compared to just
  using an @(':expand') hint.  And it was a lot easier to leave @('ppr1') and
  @('ppr1-lst') enabled and let ACL2 decide when to expand them than it was to
  disable them and control their expansion by hints and lemmas.  One take-home
  lesson for us was that ACL2's heuristics for opening recursive functions are
  pretty good!</p>

  <p>Ignoring scenario 7 &mdash; where the additional improvement came from a
  completely different source, namely, avoiding the expansion of @('MAX')
  expressions &mdash; the difference between the easiest thing to do (scenario
  3) and the fastest method that focused on manually controlling @('ppr1') and
  @('ppr1-lst') (scenario 5) was less than 4 seconds.  So, as usual with all
  kinds of performance optimization, don't get sucked down the rabbit hole!
  Take the easy wins and get on with the rest of your project!</p>

  <h3>Conclusion</h3>

  <p>Of course, whether fine induction schemes will improve other proofs just
  depends on how many irrelevant induction hypotheses are present and how
  complicated it is to simplify the terms in the theorem.  If you are proving
  something about a recursive function that contains @('let*') expressions in
  which some of the bindings conditionally make recursive calls, be alert to
  the possibility that adjusting ruler-extenders to include @(':lambdas') may
  give better inductive performance.  If you witness the prover engaged in
  fairly deep case splits, even as it seems always to prove the resulting
  cases, you might look for ways to get a finer induction case analysis.</p>")
other
(defxdoc induction-depth-limit
  :parents (induction)
  :short "The maximum number permitted of nested inductions"
  :long "<p>ACL2 may limit the number of levels of induction.  Consider for
 example a subgoal with this @(see goal-spec):</p>

 @({
 Subgoal *1.2.3.1.2.3.1.2.3/7'11'
 })

 <p>This represents nine levels of induction.  By default, that is the maximum
 permitted, since proofs rarely succeed with more than a few levels of
 induction.  (Indeed, one is well served by relying on only one level of
 induction, avoiding nested inductions in favor of proving suitable @(see
 rewrite) rules.  See @(see the-method).)  Thus, if ACL2 would otherwise
 attempt to push the subgoal indicated above for later proof by induction, the
 overall proof would fail because that would cause the maximum nesting depth of
 9 to be exceeded.</p>

 <p>To see the current limit:</p>

 @({
 (induction-depth-limit (w state))
 })

 <p>This limit is always a natural number, with one exception: it can be
 @('nil'), which means that there is no limit on the nesting depth of
 inductions.</p>

 <p>Note that an explicit @(':induct') hint (see @(see hints)) will cause an
 induction to occur, regardless of the induction-depth-limit.  Of course, if
 we have already reached the induction-depth-limit at the point the
 @(':induct') hint is applied, then any attempt to push a subgoal for induction
 will fail (unless it too has an associated @(':induct') hint).</p>

 <p>To change the limit, see @(see set-induction-depth-limit).</p>

 <p>For another way to limit the lengths of proof attempts, see @(tsee
 set-subgoal-loop-limits).</p>")
other
(defxdoc induction-heuristics
  :parents (rule-classes)
  :short "How ACL2 selects induction schemes"
  :long "<p>This topic is for those curious about induction heuristics in ACL2.
 It is not necessary to understand those heuristics to be able to use ACL2
 successfully.</p>

 <p>ACL2's heuristics for generating an induction scheme for a conjecture are
 very similar to Nqthm's and can trace their roots all the way back to the
 Edinburgh Pure Lisp Theorem Prover, the first prover to support induction in a
 general setting.</p>

 <p>For a detailed description of how ACL2 generates induction schemes see <a
 href='http://www.cs.utexas.edu/users/moore/publications/acl2-induction-heuristics.pdf'>``ACL2
 Induction Heuristics.''</a> That paper is intended for a general audience
 familiar with induction but not necessarily familiar with theorem provers or
 ACL2.  However, it can also serve as a guided tour through that part of the
 ACL2 source code that creates and selects induction schemes.</p>")
other
(defxdoc infected-constraints
  :parents (encapsulate)
  :short "@(tsee Events) 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 an event introducing a function
 symbol inside @('encapsulate') event affects the constraint exported for the
 function introduced in the @(see signature) list of that @('encapsulate').
 That function is typically introduced with @(tsee defun), but it could be
 introduced in a signature list of a subsidiary @('encapsulate') event or in a
 @(tsee defchoose) event.  Below we'll discuss the case of @('defun'), but the
 others are completely analogous for an @('"Infected"') warning.</p>

 <p>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>")
other
(defxdoc initialize-event-user
  :parents (output-controls)
  :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-system 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-system initialize-event-user my-init)
  (defattach-system 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 !>
 })")
other
(defxdoc installation
  :parents (acl2 about-acl2)
  :short "Installing ACL2"
  :long "<p>See the @(see installation-instructions) for steps to install ACL2
 on Unix-like systems (Linux, macOS, and FreeBSD).</p>

 <p>If you encounter problems installing ACL2, or need more information, see @(see
 installation-support).</p>

 <p>See @(see copyright) for information about copyright, license, and
 authorship of the ACL2 system, and see @(see acknowledgments) for
 sponsorship information.</p>

 <p>For a variant of ACL2 that supports reasoning about the real numbers, see
 @(see real).</p>

 <p>See @(see mailing-lists) for information about mailing lists for ACL2
 users, including how to post and how to access archives.</p>

 <p>ACL2 may be exported to any countries except those subject to embargoes
 under various laws administered by the Office of Foreign Assets
 Control (&ldquo;OFAC&rdquo;) of the U. S. Department of the Treasury.</p>

 <p>For more information about getting started with ACL2, see @(see
 start-here).  Also see @(see using-acl2) for information about running ACL2
 and about its @(see documentation).</p>")
other
(order-subtopics installation
  (installation-instructions obtaining-common-lisp
    installation-support
    using-acl2))
other
(defxdoc installation-instructions
  :parents (installation)
  :short "ACL2 installation instructions for Unix-like systems"
  :long "<p>These instructions describe how to install ACL2 on &ldquo;Unix-like
 systems&rdquo;, including Linux, macOS (with Intel or ARM processors),
 and FreeBSD.  To install ACL2 on Windows, see @(see windows-installation).</p>

 <p>ACL2 installations include both the ACL2 system and the open-source ACL2
 libraries developed by the ACL2 community, called the
 <see topic='@(url community-books)'>Community Books</see>.</p>

 <ol>

 <li>Decide which of the following you want to install:
   <ul>
         <li>The <b>latest ACL2 release</b>
         (<see topic='@(url note-8-6)'>version 8.6</see>).  The release is
         stable and very well tested but does not include any improvements
         or fixes made since October, 2024.  It may be appropriate
         if you do not need the very latest tools and libraries and
         do not plan to contribute to the @(see community-books).  A
         <see topic='@(url pre-built-binary-distributions)'>pre-built
         binary distribution</see> of the release may be available for
         your platform, which can let you avoid following these installation
         instructions.</li>

         <li>The <b>latest development snapshot</b> from GitHub (likely at most
         a few days old). Development snapshots are only minimally tested and
         may (rarely) have problems.  However, they provide the latest iteration
         of ACL2 and the @(see community-books).  Use a development
         snapshot if you plan to
         <see topic='@(url github-commit-code-using-pull-requests)'>
         contribute</see> additions or changes to the
         @(see community-books), or if you plan to
         update your copy of ACL2 later.  Pre-built binary distributions of
         development snapshots are generally not available.</li>
   </ul>
 </li>

<p/>

 <li>Obtain a Common Lisp implementation if you don't already have one; see
 @(see obtaining-common-lisp).  (Note: Some of the
 @(see community-books) depend on @(see Quicklisp), and those are only
 guaranteed to work with CCL or SBCL.)</li><p/>

 <li>Depending on your decision in Step 1, download ACL2 by doing
     either of the following:
    <ul>
        <li><b>For the latest ACL2 release</b> (version 8.6):
          <ol>
            <li>Change to a directory that does not already contain a
            subdirectory called @('acl2-8.6').</li>
            <li>Download <a href='https://github.com/acl2-devel/acl2-devel/releases/download/8.6/acl2-8.6.tar.gz'>
            @('acl2-8.6.tar.gz')</a> to that directory.</li>
            <li>Execute the following:
            @({
            tar xfz acl2-8.6.tar.gz
            cd acl2-8.6
            })</li>
          </ol>
          The new subdirectory @('acl2-8.6') should now
          be your shell's current directory.
        </li>

        <li><b>Or, for the latest development snapshot</b>:
          <ol>
            <li>Change to a directory that does not already contain a
            subdirectory named @('acl2').</li>
            <li>Execute the following:
            @({
            git clone https://github.com/acl2/acl2
            cd acl2
            })</li>
          </ol>
          The new subdirectory @('acl2') should now be
          your shell's current directory.
        </li>
    </ul>
 </li><p/>

 <li>Compile ACL2:

 @({
 make LISP=<your_command_to_run_lisp>
 })

 where @('<your_command_to_run_lisp>') is a command that runs
 your selected Common LISP and is not merely a shell alias. The
 default for @('<your_command_to_run_lisp>') is @('ccl').

 <b>Note:</b> You will need GNU Make (preferably newer than Version 3.82).

 This will create an executable script named @('saved_acl2') (in the
 current directory) that can be used to run ACL2.</li><p/>

 <li>Optionally, test ACL2 as follows:
 @({
 ./saved_acl2
 :mini-proveall
 (quit)
 })
 You should see "Mini-proveall completed successfully." a few lines above
 the bottom of the output.</li><p/>

 <li>Certify some books, for example with

 @({
 make basic
 })

 or something fancier such as the following.

 @({
 (time nice make -j 8 ACL2=/u/smith/bin/acl2 basic) >& make-basic.log
 })

 This may take only a few minutes, depending your @('-j') value,
 your machine, and your host Common Lisp.  The
 resulting log should contain no occurrences of the string
 &ldquo;CERTIFICATION FAILED&rdquo;; a normal exit (status 0) should guarantee
 this.  If you want further options or additional explanation (e.g.,
 you can certify many more books with @('make regression'), and there is a
 discussion of avoiding root login), see @(see books-certification).</li>

 </ol>

 <p>You now have an executable script called @('saved_acl2') and
 access to certified community books.  Enjoy!  And please
 consider contributing to the ACL2 libraries; see @(see
 how-to-contribute).</p>")
other
(defxdoc installation-support
  :parents (installation)
  :short "Additional support for ACL2 installation"
  :long "<p>To install ACL2, it will generally suffice to see the
 @(see installation-instructions).  You should read the subtopics below only if
 those instructions were somehow not sufficient.  They provide alternate and
 additional information for obtaining and installing ACL2 and associated
 libraries.</p>")
other
(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 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 @(see 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 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 @(see
 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 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 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 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>")
other
(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 integers (or
 else causes a @(see guard) violation; see @(see guard)).  @('Int=') is
 intended to execute more efficiently on integers than @(tsee equal) or @(tsee
 =), though this may not be true for all host Lisps.</p>

 @(def int=)")
other
(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)")
other
(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)")
other
(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)")
other
(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>")
other
(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 the @(see
 tours) 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 ensures 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.  Also see @(see publications) and see the presentations in each of the
 ACL2 @(csee Workshops).</p>")
other
(defxdoc interfacing-tools
  :parents (top)
  :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>.")
other
(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 @('intern') is 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" '(COMMON-LISP::X))
 })

 <p>then in Common Lisp @('(symbol-package-name (intern "X" "P"))') returns
 @('"COMMON-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>")
other
(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>")
other
(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 COMMON-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 COMMON-LISP::CAR (i.e., ACL2::CAR)

  (intern-in-package-of-symbol "car" w) is MY-PKG::|car|
 })")
other
(defxdoc intersection$
  :parents (lists acl2-built-ins)
  :short "Elements common to the given lists"
  :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 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)")
other
(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>")
other
(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)")
other
(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 evaluate, 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, which
 carries some risk; see @(see q).  The prompt in raw Lisp is generally
 different from the ACL2 prompt but that is outside our our control and varies
 from Lisp to Lisp.  See @(see prompt).  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>")
other
(defxdoc introduction-to-apply$
  :parents (apply$)
  :short "Background knowledge on how to use @(tsee apply$), @(tsee
 defwarrant), etc."
  :long "

  <h3>Background and Organization</h3>

  <p>@('Apply$') is the ACL2 version of LISP's @('apply') function.  It takes a
  ``function'' and a list of argument values, applies the function to the
  arguments, and returns the result.  For example, @('(apply$ 'expt (list 2
  8))') returns 256.</p>

  <p>A good introduction to the basic ideas and challenges of adding
  @('apply$') to ACL2 is 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, <i>Journal of Automated Reasoning</i>, Springer,
  <b>64</b>, pp 391-422, 2018.  We refer to the paper simply as ``the paper.''
  Some aspects of the paper are no longer accurate because the implementation
  of @('apply$') has matured since 2018.  But as a basic introduction, rather
  than a reference guide or user's manual, the paper is a good place to start.
  It provides motivations and challenges, succinct and precise definitions of
  relevant concepts, lots of examples, a model and meta-level proof that the
  extended theory is consistent, and a discussion of the limitations and of
  related work.  The model described in the paper is illustrated concretely in
  the certified books under @('books/projects/apply-model/').  See the
  @('README') file there.</p>

  <p>The current documentation topic takes a slightly more informal approach
  but covers much of the same ground.  In particular, after some preliminary
  remarks we coach you through a few simple simple exercises involving
  @('apply$') and related concepts.  During these exercises we draw your
  attention to some basic lessons to keep in mind.  At the end of this topic we
  list some simple challenge problems.</p>

  <p>This topic links to reference-level documentation for @(tsee apply$) and
  those other concepts.  But if you are just getting started with @('apply$')
  we recommend that you work your way through this topic, including doing the
  examples described below, without following all the links.</p>

  <h3>Challenges and Basic Solutions</h3>

  <p>The unreachable goal of this work is to allow the ACL2 user to pass
  `functions' as objects and to apply them.  That goal is unreachable because
  ACL2 remains a first order system.  However, we can identify a certain
  syntactic class of ordinary ACL2 objects, called the `@(see tame)
  functions' (which are in fact <i>not</i> functions but are merely symbols and
  list expressions) and we can allow names of functions with certain tameness
  properties to be passed around and used as functions.</p>

  <p>By the way, in this documentation topic we tend to display certain symbols
  sometimes in uppercase and sometimes in lowercase.  They denote the same
  symbol.  But we use uppercase when we're using the symbol as a quoted
  constant to be passed to @('apply$') and we use lowercase when we're using
  the symbol as a function symbol in a term.</p>

  <p>``Tameness'' imposes strict rules on how functional arguments are used.
  We'll discuss it further below.</p>

  <p>The fundamental question raised by @('apply$') is ``How can @('apply$')
  know the correspondence between an ordinary ACL2 object, like a symbol or a
  list, and the ACL2 function the user means to apply?''  For example, if the
  user defines the function @('my-append'), how can @('apply$') know that
  @('(apply$ 'MY-APPEND (list a b))') should expand to @('(my-append a b)')?</p>

  <p>The ACL2 primitives can be built in.  The logical definition of @('apply$')
  includes a big case split that recognizes about 800 ACL2 primitives, so that
  for example:</p>

  @({(apply$ 'car (list a)) = (car a)})

  <p>and</p>

  @({(apply$ 'assoc-equal (list a b)) = (assoc-equal a b).})

  <p>But user-defined functions are problematic because once @('apply$') has been
  defined in the ACL2 sources it cannot be extended to handle new symbols.</p>

  <p>Intuitively, if you have defined the @('n')-ary function @('foo') then you
  would expect @('(apply$ 'foo (list a1...an))') to be @('(foo a1...an)').  One
  way to arrange that might be to leave @('apply$') undefined on the symbol
  @('foo') but to assume, as by a new axiom or hypothesis,</p>

  @({
  forall a1...an : (apply$ 'foo (list a1...an)) = (foo a1...an).
  })

  <p>It will turn out that using new axioms for this purpose is a bad idea.
  Hiding the link between @('apply$') and new symbols in axioms raises a
  problem with ACL2's notion of @(tsee LOCAL).  This is called ``the @('LOCAL')
  problem'' and we illustrate it later in this doc topic.  But for that reason,
  the suppositions extending @('apply$') will take the form of hypotheses to be
  added to conjectures in which the behavior of @('apply$') on new symbols is
  important.  These hypotheses are called ``@(tsee warrant)s.''</p>

  <p>Warrant (Merriam-Webster): (noun) a commission or document giving
  authority to do something....</p>

  <p>In our case, a warrant for @('fn') gives @('apply$') permission to apply
  @('fn') under some circumstances, by asserting a universally quantified
  conditional equality about @('apply$')'s behavior on @(''fn'). It also tells
  @('apply$') and the @(see tame)ness predicates things like how many arguments
  @('fn') takes and how it uses them by asserting the @(tsee badge) of
  @(''fn').  The @('badge') of @('fn') is an ACL2 object that contains various
  tokens interpretable by @('apply$') and the tameness predicates.</p>

  <p>But there is a fundamental logical problem: it is not always possible to
  satisfy such suppositions. There may be no way that @('apply$') could handle
  @('fn').  An example of a @('fn') for which that hypothesis is unsatisfiable
  is</p>

  @({
  (defun russell (x y) (not (apply$ x (list y y)))).
  })

  <p>This definition of @('russell') is not recursive: it does not call itself.
  So this definition is admissible.  But if we had a warrant for @('apply$')
  and that @('warrant') were as simple as</p>

  @({forall x,y : (apply$ 'russell (list x y)) = (russell x y)})

  <p>then we would have this classical problem with self-reference:</p>
  @({
  (russell 'russell 'russell)
  =                                      {def russell}
  (not (apply$ 'russell (list 'russell 'russell)))
  =                                      {warrant russell}
  (not (russell 'russell 'russell))
  })

  <p>which is contradictory.</p>

  <p>This problem is addressed by introducing the notion of ``tameness.''
  Tameness is a syntactic property of terms and functions that implies that it
  is ok to ``extend'' @('apply$') to handle them.</p>

  <p>It should be pretty clear that if the user defines an ACL2 function that
  in no way depends on @('apply$'), e.g., a function like:</p>

  @({(defun sq (x) (* x x))})

  <p>then the hypothesis</p>

  @({
  forall x : (apply$ 'SQ (list x)) = (sq x)
  })

  <p>is satisfiable: we could have introduced @('sq') before @('apply$') and
  then defined @('apply$') in the first place to handle that particular
  symbol.</p>

  <p>@('Sq') is a particularly simple example of a tame function.  One
  challenge in this work has been to extend the notion of tameness so that it
  includes a lot of what a normal ACL2 programmer might want in @('apply$')
  while maintaining the soundness of the resulting theory.</p>

  <p>For example, consider the following function, which maps a given function
  over a list and collects the results.</p>

  @({
  (defun my-collect$ (fn lst)
    (if (endp lst)
        nil
        (cons (apply$ fn (list (car lst)))
              (my-collect$ fn (cdr lst)))))
  })

  <p>Our definition of tameness considers <tt>(my-collect$ 'SQ lst)</tt> to be a
  tame expression, even though @('my-collect$') calls @('apply$').  The reason we
  can allow this is that in this particular call of @('my-collect$') the function
  to be applied is itself tame.  But if <tt>(my-collect$ 'SQ lst)</tt> is a tame
  expression, then <tt>'(LAMBDA (LST) (MY-COLLECT$ 'SQ LST))</tt> is a tame
  function and thus</p>

  @({(my-collect$ '(LAMBDA (LST) (MY-COLLECT$ 'SQ LST)) z)})

  <p>is a tame expression.  So, for example, at the top-level of ACL2 one
  can do this:</p>

  @({
  ACL2 !>(my-collect$ '(LAMBDA (LST) (MY-COLLECT$ 'SQ LST))
                   '((1 2 3) (4 5 6) (7 8 9)))
  ((1 4 9) (16 25 36) (49 64 81))
  })

  <p>Of course, this presumes we have defined @('sq') and @('my-collect$') and have
  analyzed them to make sure they have the appropriate tameness properties.
  (Note that @('my-collect$') is not tame, but the way it uses its ``functional''
  argument is crucial to the tameness of <tt>(my-collect$ 'SQ lst)</tt>.)  To use
  @('apply$') to full advantage we need to have analyzed every relevant
  function definition so we know which arguments are treated like functions and
  whether they are used in accordance with our restrictions.  So if you're
  defining a function you intend to @('apply$') it is convenient to define it
  with the new command @(tsee defun$), which is just an ordinary @(tsee defun)
  followed by a @(tsee defwarrant) command.  If you've already defined the
  function and then realize you wish to @('apply$') it, you can call
  @('defwarrant') yourself.</p>

  <p>@('Defwarrant') analyzes a @(':')@(tsee logic) mode definition and
  produces a badge and a warrant, if possible.  Also relevant is the @(tsee
  defbadge) command which issues a badge for a function (if possible) but does
  not issue a warrant.  Its primary purpose is to allow @(':')@('program') mode
  functions to be analyzed and badged so they can be safely executed by
  @('apply$') at the top-level ACL2 loop.  But the present discussion focuses
  primarily on the logical machinery, which requires warrants.</p>

  <p>We explain further via an annotated example, starting from scratch but
  from the basic background just sketched.  For many additional examples, see
  @(see community-books) @('books/projects/apply/report.lisp') which is a
  certified book containing the examples in the paper.</p>

  <p><b>Note carefully:</b> the directory @('books/projects/apply-model/'),
  mentioned earlier in conjunction with the paper, is different from the
  directory @('books/projects/apply/') just mentioned!  The former directory
  concerns the logical foundations of @('apply$') as they stood when the paper
  was written.  The latter is more directly relevant to ACL2 users and provides
  useful lemmas about @('apply$') as it is axiomatized and implemented today.
  It also includes many example theorems.</p>

  <h3>Exercises and Lessons</h3>

  <p>To get started, fire up your ACL2 and define two ordinary ACL2 functions,
  one that squares its argument and the other that reverses its argument.  We
  show the ACL2 prompt below in front of each form we expect you to execute.</p>

  @({
  ACL2 !>(defun sq (x) (* x x))

  ACL2 !>(defun rev (x)
           (if (endp x)
               nil
               (append (rev (cdr x)) (list (car x)))))
  })

  <p><b>Lesson 0:</b> Learn about @('apply$') by reading this tutorial
  introduction.  But this tutorial mentions many undefined concepts: tameness,
  warrants, badges, ilks.  These concepts are intertwined with @('apply$') and
  warrants through mutual recursion, constraints, rewrite rules, etc..  So we
  decided not to try to define them here as we go along, though the links
  provided do provide definitive descriptions.  So please tolerate the use of
  undefined words here &mdash; we'll try to give you a sense of what they
  mean.</p>

  <p><b>Lesson 1:</b> To use @('apply$'), be sure to include the following book
  of lemmas.  These lemmas are important not just to proving theorems about
  @('apply$') but to defining functions that use @('apply$').</p>

  @({
  ACL2 !>(include-book "projects/apply/top" :dir :system)
  })

  <p><b>Lesson 2:</b> To allow @('apply$') to ``work'' on a function symbol the
  symbol must be ``warranted.''  Actually, of course, you can pass anything to
  @('apply$') and the axioms will reduce it to some value: ACL2 is untyped and
  all functions are total!  But @('apply$') won't work in the logic as you
  expect if the first argument to @('apply$') is not warranted!  (And
  @('apply$') won't work as you expect for top-level evaluation if its first
  argument is not at least badged.)  To issue warrants (and badges) for @('sq')
  and @('rev') do:</p>

  @({
  ACL2 !>(defwarrant sq)

  ACL2 !>(defwarrant rev)
  })

  <p>@(tsee Defwarrant) checks that its argument, <i>fn</i>, is a defined
  function symbol that satisfies certain restrictions on how it uses its
  arguments, restrictions that enable us to define the tameness predicates and
  that allow @('apply$') to ``work'' without causing logical contradictions.
  @('Defwarrant') causes an error if <i>fn</i> does not obey our rules.  But if
  @('defwarrant') does not cause an error it produces a ``badge'' for <i>fn</i>
  that describes which formals are treated as ``functions.''  Henceforth, we'll
  say such formals have ``@(see ilk)'' @(':FN').  In addition to computing a
  badge, non-erroneous calls of @('defwarrant') introduce a &ldquo;@(tsee
  warrant) function&rdquo; for <i>fn</i>.  The warrant function for <i>fn</i>
  is a 0-ary function named @('apply$-warrant-')<i>fn</i>.  A call of the
  warrant function, i.e., the term @('(apply$-warrant-')<i>fn</i>@(')') is
  called the &ldquo;warrant&rdquo; for <i>fn</i> and if the warrant for
  <i>fn</i> is included among the hypotheses of a conjecture then @('(apply$
  '')<i>fn</i>@(' (list a1 ... an))') can expand to @('(')<i>fn</i>@(' a1
  ... an)'), provided the @('ai') meet the tameness requirements required by
  <i>fn</i>'s badge.</p>

  <p><b>Lesson 3:</b> We'll say more about tameness, badges, and warrants
  later.  You already know that warrants can only be issued for @(':logic')
  mode functions because the function symbol is used as a function in the
  logical definition of the warrant.  But you might as well learn four major
  limitations of @('apply$'):
  (i) @('Apply$') does not take @(tsee STATE) or @(see stobj) arguments and so
  cannot call any function that takes @('STATE') or @('stobj') arguments.  (ii)
  @('Apply$') cannot call a function whose measure, well-founded relation, or
  domain predicate depends on @('apply$'). (iii) @('Apply$') cannot call a
  function that itself uses @('apply$') unless that function's measure is a
  natural number or a lexicographic combination of naturals formed with
  @('llist') as defined in the Community Books at @('books/ordinals/'). (iv)
  @('Apply$') cannot call a function that itself uses @('apply$') if that
  function was defined mutually recursively.  Another way of saying all this is
  that @('defwarrant') will cause an error if you try to warrant a function
  violating (i), (ii), (iii) or (iv).</p>

  <p><b>Lesson 4:</b> If you want to define a function and immediately call
  @('defwarrant') on it you can use the handy macro @('defun$').  We'll use
  @('defun$') freely below.</p>

  <p><b>Lesson 5:</b> You can define functions that take warranted
  ``functions'' as arguments and @('apply$') them.  Here is a function that
  applies its first argument to every element of its second argument and
  collects the results.  We sometimes call functions like @('my-collect$')
  ``mapping functions'' because they map another function over some range.  We
  would call them ``functionals'' except that suggests ACL2 is higher-order and
  it is not!  So we most often call them @(see scion)s of @('apply$').  In
  ordinary English usage, a ``scion'' is a descendant of an important family or
  individual; our scions are ``descendants'' of @('apply$') and inherit its
  power and restrictions.</p>

  @({
  ACL2 !>(defun$ my-collect$ (fn lst)
           (if (endp lst)
               nil
               (cons (apply$ fn (list (car lst)))
                     (my-collect$ fn (cdr lst)))))
  })

  <p>In this definition, the first argument has ilk @(':FN') because it is used
  exclusively as a ``function:'' it reaches the first argument of @('apply$')
  and is untouched otherwise.  The second argument has ilk @('NIL') and we say
  it's ``ordinary.''  It is <i>never</i> used as a function.</p>

  <p>Note: We define @('my-collect$') with @('defun$') simply to illustrate
  @('defun$').  Unless we mean to pass @('my-collect$') to @('apply$') or to
  some scion in the future, there is no reason to have a warrant for
  @('my-collect$').  Had we defined @('my-collect$') with the ordinary
  @('defun') and realized later that we want to pass @(''MY-COLLECT$') into a
  slot of ilk @(':FN'), we could get a warrant for @('my-collect$') by calling
  @('(defwarrant my-collect$)').</p>

  <p>Actually, the function @('collect$') is pre-defined in ACL2 and behaves
  like @('my-collect$').  We chose to introduce @('my-collect$') simply to
  illustrate that new scions can be introduced and used.  Here's another useful
  pre-defined scion.  You won't need to define it in your ACL2 session to use
  it.</p>

  @({
  (defun$ always$ (fn lst)
    (if (endp lst)
        t
        (and (apply$ fn (list (car lst)))
             (always$ fn (cdr lst)))))
  })

  <p>It checks that every element of @('lst') satisfies its @(':FN') argument
  @('fn').</p>

  <p>The reason that both @('collect$') and @('always$') are pre-defined is
  that they are part of the support for the @(tsee loop$) statment.</p>

  <p><b>Lesson 6:</b> You can run scions on warranted function symbols:</p>

  @({
  ACL2 !>(my-collect$ 'SQ '(1 -2 3 -4))
  (1 4 9 16)

  ACL2 !>(my-collect$ 'rev '((1 2 3) (4 5 6) (7 8 9)))
  ((3 2 1) (6 5 4) (9 8 7))
  })

  <p>You might wonder why you can run @('my-collect$') on @(''SQ') &mdash; which
  evaluates @('apply$') on @(''SQ') &mdash; without explicitly acknowledging
  the warrant that links @('(apply$ 'SQ (list a))') to @('(sq a)').  The reason
  is that evaluation in ACL2's top-level read-eval-print loop assumes all
  existing warrants are provided.  Warrants only become important when we start
  dealing with proofs.</p>

  <p><b>Lesson 7:</b> You can run scions on tame quoted @('LAMBDA') objects.
  These @('LAMBDA') objects can even include calls of scions, provided
  they are tame.</p>

  @({
  ACL2 !>(my-collect$
               (lambda$ (x) (CONS 'SQUARES (MY-COLLECT$ 'SQ x)))
               '((1 2 3) (4 5 6)))
  ((SQUARES 1 4 9) (SQUARES 16 25 36))
  })

  <p>Note that the ``function symbols'' in the ``body'' of a quoted @('LAMBDA')
  object may reach @('apply$') as the @('LAMBDA') object is applied.</p>

  <p>@('LAMBDA') objects are just quoted list expressions that start with the
  symbol @('LAMBDA') and look like lambda-expressions.  But quoted @('LAMBDA')
  objects have to have fully translated bodies and meet other restrictions so
  @('apply$') can interpret them.  You cannot use macros like @('+') or
  @('cond') and must you quote all constants.  We urge you not to try to type
  quoted @('LAMBDA') objects by hand!  Instead, we provide a macro, @(tsee
  lambda$), that allows you to write lambda expressions in untranslated
  form.</p>

  <p><b>Lesson 8:</b> There are three very similar looking but very different
  notions used in this documentation: lambda expressions, @('LAMBDA') objects,
  and @('lambda$') expressions.  Read carefully!  See @(tsee lambda) for some
  definitions and disambiguation help.  The @('LAMBDA') objects reaching
  @('apply$') must be fully translated (and tame) to be handled correctly.  The
  special macro @('lambda$') will translate for you.</p>

  @({
  ; Don't type quoted LAMBDA objects like this!
  ACL2 !>(my-collect$ '(LAMBDA (x)
                         (IF (< x '0) (BINARY-* '10 x) (SQ x)))
                      '(1 -2 3 -4))
  (1 -20 9 -40)

  ; Type this instead!
  ACL2 !>(my-collect$ (lambda$ (x)
                         (if (< x 0) (* 10 x) (sq x)))
                      '(1 -2 3 -4))
  (1 -20 9 -40)
  })

  <p><b>Lesson 9:</b> Almost all ACL2 primitives are known to @('apply$').  For
  a complete list of the built-ins evaluate</p>

  @({
  (append '(BADGE TAMEP TAMEP-FUNCTIONP SUITABLY-TAMEP-LISTP
                  APPLY$ EV$)
          (strip-cars *badge-prim-falist*))
  })

  <p>You can freely use these ACL2 primitives with @('apply$') and in your
  @('lambda$') expressions, without warrants.</p>

  <p><b>Lesson 10:</b> You can prove and use theorems about scions.</p>

  @({
  ACL2 !>(defthm my-collect$-append
           (equal (my-collect$ fn (append a b))
                  (append (my-collect$ fn a)
                          (my-collect$ fn b))))

  ACL2 !>(thm (equal (my-collect$ (lambda$ (x) (* x x))
                                  (append c d))
                     (append (my-collect$ (lambda$ (x) (* x x)) c)
                             (my-collect$ (lambda$ (x) (* x x)) d))))
  })

  <p>Notice that the lemma @('my-collect$-append') talks about an arbitrary
  @('fn').  The definition of @('apply$') is completely irrelevant to this
  theorem!  Once @('my-collect$-append') has been proved can be instantiated
  with anything for @('fn').  This is demonstrated when the @('thm') above is
  proved: the proof is just to rewrite with @('my-collect$-append').  Notice
  that the only function being @('apply$')'d in the @('thm') above is the
  primitive multiplication function, which is built into apply$.</p>

  <p><b>Lesson 11:</b> But when your theorems depend on the behavior of
  @('apply$') on particular user-defined functions, you will need to provide
  hypotheses stipulating the behavior of @('apply$') on those values.  Those
  hypotheses are the <i>warrants</i> for the (non-primitive) function symbols
  involved.  Here is an example: Recall the function @('sq') defined and
  warranted above.  We might wish to prove that if @('lst') is a list of
  integers then @('(my-collect$ 'SQ lst)') is a list of natural numbers.  We
  can use @('always$') to express the notions of ``list of integers'' and
  ``list of naturals.''  We could try to state the conjecture this way:</p>

  @({
  ACL2 !>(thm (implies (always$ 'INTEGERP lst)
                       (always$ 'NATP (my-collect$ 'SQ lst)))).
  })

  <p>But the attempt to prove that formula will fail because it depends on the
  fact that the @('sq') of an integer is a natural <i>and on the assumption
  that</i> @('(apply$ 'SQ (list x))') <i>is</i> @('(sq x)').  That assumption
  is what the <i>warrant</i> for @('sq') tells us.  Thus, the warrant for
  @('sq') is required as a hypothesis!  The following theorem can be
  proved.</p>

  @({
  ACL2 !>(defthm all-natp-collect$-sq
           (implies (and (warrant sq)
                         (always$ 'INTEGERP lst))
                    (always$ 'NATP (collect$ 'SQ lst))))
  })

  <p>Note that we don't need to provide warrants for @('integerp') or @('natp')
  because they are ACL2 primitives and thus built into the behavior of
  @('apply$').  But we must provide the warrant for @('sq') because we know the
  proof depends on @('(apply$ 'sq (list x1 ...))') simplifying to @('(sq
  x1)').</p>

  <p>The macro form @('(warrant f1 ... fk)') expands to the conjunction of the
  warrants for the @('fi')s.  That is</p>
  @({
  (warrant f1 ... fk)
  =
  (and (apply$-warrant-f1)
       ...
       (apply$-warrant-fk)).
  })

  <p>If you attempt a proof and it fails, and you see among the checkpoints
  terms of the form @('(apply$ 'fn (list a1 ... an))'), then you probably
  forgot to call @('defwarrant') on @('fn') and @('apply$') doesn't know what
  to do with that symbol!  If, on the other hand, you see a @(see
  forcing-round) checkpoint that is attempting to prove a warrant, like
  @('(apply$-warrant-fn)'), then you probably forgot to add the warrant for
  @('fn') to the hypotheses of the conjecture you're trying to prove.</p>

  <p><b>Lesson 12:</b> Warrants solve the ``@('LOCAL') problem.''  Imagine the
  trouble we'd be in if the theorem above did not require a warrant on @('sq').
  We could get away with this:</p>

  @({
  (encapsulate nil
    (local (defun sq (x) (* x x)))
    (defthm unwarranted-all-natp-collect$-sq
      (implies (always$ 'INTEGERP lst)
               (always$ 'NATP (collect$ 'SQ lst)))))

  (defun sq (x) (* x x x))

  (thm (implies (always$ 'INTEGERP lst)
                (always$ 'NATP (collect$ 'SQ lst))))
  })

  <p>This would be a disaster because the final @('thm') is invalid since
  @('(sq -2)') here is @('-8') and yet the @('thm') is trivially proved by
  appealing to the unwarranted theorem exported from the encapsulate.</p>

  <p>If we could prove the unwarranted theorem we could export it because it
  does not mention or depend on the locally defined function @('sq'), it just
  mentions the constant symbol <tt>'SQ</tt>.  Fortunately, we cannot actually
  prove the unwarranted version of the theorem because there is no <i>a
  priori</i> connection between @('(apply$ 'SQ (list x))') and @('(sq x)').
  And if we add the warrant for @('sq') to the @('defthm') in the encapsulate
  we can prove the theorem but then we cannot export it because the warrant
  ancestrally depends on locally defined function @('sq').</p>

  <p><b>Lesson 13:</b> While we may have given the impression that we've
  provided a convenient fragment of second-order functionality in ACL2 its
  limitations will annoy you!  For example, when ACL2 tries to use the
  lemma</p>

  @({
  (defthm all-natp-collect$-sq
    (implies (and (warrant sq)
                  (always$ 'INTEGERP lst))
             (always$ 'NATP (collect$ 'SQ lst))))
  })

  <p>it just employs its usual first-order matching algorithm.  Thus, the lemma
  won't apply to</p>

  @({
  (always$ 'NATP (collect$ (lambda$ (x) (* x x)) lst))
   })

  <p>because the constant symbol <tt>'SQ</tt> is not the same as the constant
  list generated by translating @('lambda$') expression,
  <tt>@(''(LAMBDA (X) (BINARY-* X X))')</tt>, even though they are equivalent
  if understood as functions.  See the discussion at @(tsee fn-equal).</p>

  <p><b>Lesson 14:</b> Recall Lesson 0!  Before you start to use @('apply$')
  outside of this simple demo script, we advise you to read the documentation
  for @('apply$').</p>

  <p><b>An Advanced Lesson:</b> We conclude this tutorial by defining one of
  the most useful scions and proving a couple of theorems illustrating its
  flexibility: @('foldr').</p>

  @({
  ACL2 !>(defun$ foldr (lst fn init)
           (if (endp lst)
               init
               (apply$ fn
                       (list (car lst)
                             (foldr (cdr lst) fn init)))))
  })

  <p>Note that @('foldr') maps over the list in its first argument, applying
  its second argument to two things: successive elements of the list and the
  result of recursively calling itself on the rest of the list.  It returns its
  third argument when the list is empty.</p>

  <p>When its functional argument is @('CONS') @('foldr') is just the
  concatenation of its other two arguments:</p>

  @({
  ACL2 !>(defthm foldr-cons
           (equal (foldr x 'CONS y)
                  (append x y)))
  })

  <p>We do not need a warrant for @('cons') because it is built into
  @('apply$').  In fact, the built-ins don't have warrants but if you
  unnecessarily list a primitive in a @('warrant') expression, like @('(warrant
  foldr cons)'), it just ignores the primitives that are built into
  @('apply$').</p>

  <p>By supplying a certain @('lambda') expression we can use @('foldr') to
  reverse its first argument:</p>

  @({
  ACL2 !>(defthm foldr-can-be-rev
           (implies (warrant foldr)
                    (equal (foldr x
                                  (lambda$ (x y)
                                     (FOLDR y 'CONS (CONS x nil)))
                                  nil)
                           (rev x))))
  })

  <p>Note that the @('lambda$') expression calls @('FOLDR').  Because of this,
  we must provide the warrant for @('foldr') since that inner @('foldr') will
  be applied by the outer @('foldr').  This illustrates an important point made
  in Lesson 7 above: scions can apply other scions, including themselves, as
  long as the applications are tame.</p>

  <h3>Some Practice Problems</h3>

  <p>There is no better way to learn than to practice.  So here are a few
  challenge problems.  The answers can be found in
  @('books/projects/apply/answers-to-doc-intro-to-apply.lisp').</p>

  <p><b>Problem 1</b>: Assume @('fn') is a binary relation.  Define
  @('(insert$ e lst fn)') to insert @('e') into the list @('lst') in front of
  the first element, @('d'), in @('lst') such that @('(fn e d)') is true.</p>

  <p><b>Problem 2</b>: Define @('(sort$ lst fn)') to be an insertion sort
  algorithm for the binary relation @('fn'), e.g., to successively insert each
  element into the recursively sorted remaining elements.  (Note: There is no
  assurance that @('sort$') will actually produce a list ordered by @('fn')
  because we don't know that @('fn') is an ordering relation.)</p>

  <p><b>Problem 3</b>: Study the four examples below, which illustrate perhaps
  surprising properties of our ``insertion sort'' function.  (If your
  definitions don't have these properties you should back up and redefine your
  functions as we vaguely described above!)</p>

  @({
  (defthm examples-of-sort$
    (and (equal (sort$ '(1 3 -7 0 23) '<)
                '(-7 0 1 3 23))
         (equal (sort$ '(1 3 -7 0 23)
                       (lambda$ (x y) t))
                '(1 3 -7 0 23))
         (equal (sort$ '(1 3 -7 0 23)
                       (lambda$ (x y) nil))
                '(23 0 -7 3 1))
         (equal (sort$ '(1 a 2 x b 3 4 y c)
                       (lambda$ (x y) (symbolp x)))
                '(a x b y c 4 3 2 1)))
    :rule-classes nil)
  })

  <p><b>Problem 4</b>: Prove the following theorem suggested especially by the
  last example above.  To state this theorem we first introduce the familiar
  reverse function, @('rev').</p>

  @({
  (defun rev (x)
    (if (endp x)
        nil
        (append (rev (cdr x))
                (list (car x)))))
  })

  <p>and we use the pre-defined function @('(when$ fn lst)') which computes the
  elements of @('lst') satisfying the unary-function @('fn'), in the order in
  which they occur, e.g., @('(when$ '(1 a 2 b) 'symbolp)') is @(''(a b)').</p>

  <p>Prove</p>

  @({
  (defthm sort$-lambda-symbolp
    (implies (true-listp lst)
             (equal (sort$ lst (lambda$ (x y) (symbolp x)))
                    (append (when$ 'symbolp lst)
                            (rev
                              (when$
                                (lambda$ (x y) (not (symbolp x)))
                                lst))))))
  })

  <p>Lemmas will be needed.</p>

  <p><b>Problem 5</b>: Define @('(orderedp$ lst fn)') to check whether @('fn')
  holds between each adjacent pair of elements in @('lst').  Test your function
  with</p>

  @({
  (defthm examples-of-orderedp$
    (and (orderedp$ '(1 3 5 7) '<)
         (not (orderedp$ '(1 3 3 5 7) '<)))
    :rule-classes nil)
  })

  <p><b>Problem 6</b>: You might hope that @('(orderedp$ (sort$ lst fn) fn)')
  is a theorem.  But it is not as is easily shown by the example
  @('(orderedp$ (sort$ '(3 1 5 3 7) '<) '<)').  If you try to prove the
  conjecture and inspect the output you'll see that the proof fails because we
  do not know that @('(or (fn x y) (fn y x))') is true.  That is, we don't know
  that @('fn') is <i>Strongly Connected</i>.  How could we, since the
  conjecture is claimed for all @('fn')?</p>

  <p>Unfortunately, it is awkward to state that @('fn') is a strongly connected
  relation in ACL2's first-order quantifier-free language.  This is a good
  example of the limitations of ACL2's support for second-order functions!</p>

  <p>But we can prove versions of the conjecture for concrete strongly
  connected @('fn')s.  The relation named @('before-dayp'), below, is strongly
  connected, as demonstrated by the events following its definition.</p>

  <p>Carry out these events.</p>

  @({
  (defun beforep (x y lst)
    (if (and (member x lst)
             (member y lst))
        (member y (member x lst))
        t))

  (defun before-dayp (x y)
    (beforep x y '(mon tue wed thu fri sat sun)))

  (defthm before-dayp-strongly-connected
    (implies (not (before-dayp x y))
             (before-dayp y x)))

  (in-theory (disable before-dayp))
  })

  <p>Now, prove the version of @('(orderedp$ (sort$ lst fn) fn)') for the
  instance in which @('fn') is @(''before-dayp').</p>")
other
(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 descendants.</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
 descendants.</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 descendants.</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>")
other
(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>")
other
(defxdoc introduction-to-programming-in-acl2-for-those-who-know-lisp
  :parents (programming introduction-to-the-theorem-prover)
  :short "Introduction to programming in ACL2 for Lisp users"
  :long "<p>The @(see documentation) topic, @(see acl2-built-ins), as well as
 its parent topic, @(see programming), are starting points for a rich
 collection of primitives and features in the ACL2 programming language.  In
 the present topic (below) we give a succinct introduction to that language for
 those who are already reasonably familiar with Common Lisp, or perhaps another
 Lisp.  Follow the hyperlinks if you want to drill down; for example, we
 mention multiple values below but say very little about them, instead
 providing links to topics that explain their handling in a little more
 depth.</p>

 <p>The @(tsee documentation) for ACL2 and its @(see community-books) provides
 a rich set of topics for further exploration.  This particular topic is
 intended to serve only as a brief introduction to programming in ACL2 for
 those who know Lisp, especially Common Lisp.  Supplementary reading that may
 interest a few readers includes ``<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).</p>

 <h3>Applicative Common Lisp</h3>

 <p>The ACL2 (``A Computational Logic for Applicative Common Lisp'')
 programming language is essentially a subset of Common Lisp &mdash; albeit
 with some useful extensions &mdash; that is <i>applicative</i>: the value
 returned by a function depends only on its inputs, not state.  (There is an
 ACL2 notion of @(see state), introduced briefly below; but that state must be
 passed as an explicit argument.)  Many commonly-used functions and special
 forms in the applicative subset of Common Lisp are also in ACL2, such as (to
 name just a very few) @(tsee car), @(tsee cons), @(tsee nth), @(tsee append),
 @(tsee let), and @(tsee let*).  A few others are not directly included in ACL2
 because they have incomplete specifications in Common Lisp, such as @(tsee
 pairlis); according to the Common Lisp HyperSpec: ``The new pairs may appear
 in the resulting association list in either forward or backward order.''  Many
 such functions tend to have close analogues in ACL2, named by concatenating
 @('"$"') to the Common Lisp name; for example, ACL2 has @(tsee pairlis$),
 @(tsee union$), and even @(tsee random$).  Yet other Common Lisp functions,
 for example @('format'), are not available in ACL2 but have useful
 alternatives in ACL2; for example, see @(tsee fmt).  See @(see acl2-built-ins)
 for a much more comprehensive list of functions, macros, and special forms
 provided by the ACL2 programming language.  In particular, a search through
 that documentation topic for `@('$')' will show you utilities like
 @('pairlis$') that are based on related Common Lisp utilities.</p>

 <p>In the ACL2 read-eval-print loop, you can define functions and macros with
 @(tsee defun) and @(tsee defmacro) just as in Common Lisp, with some
 restrictions (see for example @(see name)) and also some additional @(tsee
 declare) forms.</p>

 <h3>Data types</h3>

 <p>Only certain Lisp data types are supported for programming in ACL2: numbers
 that are either rational numbers or complex numbers with rational
 coefficients (see @(see numbers-introduction)); the @(see characters)
 constructed with @('(code-char n)') for @('n') from 0 to 255; @(see strings)
 formed from those characters; @(see symbols) whose @(tsee symbol-name) and
 @(tsee symbol-package-name) are ACL2 strings; and objects constructed from
 others using @(tsee cons).</p>

 <p>In particular, arrays are not directly supported as an ACL2
 datatype (except for strings).  However, ACL2 supports an applicative notion
 of array, which is logically an association list but has an associated Lisp
 array that provides fast reads in single-threaded programs.  See @(see
 arrays).  If your code creates an array and does many more reads to it than
 writes, or even if there are rarely two writes to the same index (as when
 writes are primarily to initialize the array), then ACL2 arrays may perform
 well.  Otherwise you may get significantly better performance, avoiding the
 consing done by writes (to build the association list), by using a different
 sort of representation of arrays in ACL2: <i>single-threaded objects</i>, or
 <i>stobjs</i>; see @(see stobj).</p>

 <p>Structures can be simulated in ACL2 using suitable macros.  For a simple
 such macro that is built into ACL2, together with alternatives to it, see
 @(see defrec).</p>

 <h3>Program and logic modes</h3>

 <p>If you are using ACL2 as a programming language but you do not intend to
 prove anything about your code, at least not at first, then you might be
 well-served by using @(see program) mode.  In this mode, ACL2 will admit the
 definition if syntactic checks succeed, in particular without requiring a
 proof of termination for recursive definitions.  You can specify the mode
 directly in a declaration (see @(see xargs) for how to specify @(':program')
 in a @(see declare) form), or you can set the default @(see defun-mode) to
 @(':program') (see @(see default-defun-mode) and see @(see program)).</p>

 <p>When you are ready to reason about your functions, you can use @(':')@(tsee
 logic) mode instead, or you can convert a program-mode function to logic-mode
 with @(tsee verify-termination).</p>

 <h3>Connection to Common Lisp</h3>

 <p>Many Common Lisp functions should only be applied to certain types of
 objects: for example, @(tsee car) should only be applied to a cons pair or
 @('nil').  Every ACL2 function has a <i>guard</i>, which specifies the
 intended domain of the function; see @(see guard).  For example, the guard for
 @('car') is @('(OR (CONSP X) (EQUAL X NIL))').  See @(see args) for a utility
 that provides this and other information about a given function symbol.</p>

 <p>Beginning ACL2 programmers should probably ignore guards, at least
 initially.  Otherwise, see @(see xargs) for how to specify a guard; also see
 @(see verify-guards).</p>

 <h3>Multiple values</h3>

 <p>The analogues of Common Lisp utilities @('multiple-value-bind') and
 @('values') are @(tsee mv-let) and @(tsee mv), respectively.  Also see @(see
 b*) for an alternative to @(tsee let*) that can be convenient in the presence
 of multiple values.</p>

 <h3>State</h3>

 <p>ACL2 provides a notion of <i>state</i> that is useful for certain kinds of
 programming.  As mentioned above, the state must be passed explicitly because
 of the applicative nature of ACL2; indeed, it must be passed as the variable,
 @('state'), i.e., the symbol in the @('"ACL2"') package whose @(tsee
 symbol-name) is @('"STATE"').  This is a rather complex notion, perhaps best
 avoided by beginning ACL2 programmers.  To learn about the ACL2 state, see
 @(see state), which points to a topic, @(see programming-with-state), that
 discusses many utilities for reading and writing the ACL2 state.</p>

 <h3>More help</h3>

 <p>ACL2 does not provide @('apropos').  However, you can search the
 documentation to find substring matches.  For example, if you type @('princ')
 into the ``@('Jump to')'' box in the web-based manual, or if you type the
 command @('i') [for ''index''] into the @(see acl2-doc) Emacs-based
 documentation browser, you will find @(tsee princ$).  The ``@('Jump to')'' box
 in the web-based manual matches on prefixes, but the @('i') command in @(see
 acl2-doc) matches on any substring.</p>

 <p>Another way for Lisp programmers to get answers to ``How do I do this in
 ACL2'' questions is to query the acl2-help mailing list.  You can sign up via
 a link on the <a href='http://www.cs.utexas.edu/users/moore/acl2/'>ACL2 home
 page</a>.  Moreover, that could be a good place to request or suggest
 improvements to this documentation topic!  Also see @(see history) for some
 ways to query the current session.</p>

 <p>Finally, here are a few specific alternatives to Common Lisp utilities.</p>

 <ul>

 <li>@('describe'): see @(tsee doc)</li>

 <li>@('fboundp') and other utilities to provide information about functions,
 macros, and special operators: see @(tsee args)</li>

 <li>@('format'): see @(tsee fmt), which has links to related functions that
 perform formatted printing</li>

 <li>@('list-all-packages'): see @(tsee in-package); also see the description
 of @('known-package-alist') in @(see system-utilities)</li>

 <li>@('setq'): see @(tsee assign), but perhaps first look at the documentation
 topics for @(see state) and @(see programming-with-state)</li>

 <li>@('symbol-plist'): see @(tsee props), @(tsee getprop), and @(tsee
 putprop)</li>

 <li>@('with-open-file'): see @(see io)</li>

 </ul>")
other
(defxdoc introduction-to-rewrite-rules-part-1
  :parents (introduction-to-the-theorem-prover)
  :short "Introduction to ACL2's notion of rewrite rules"
  :long "<p>This topic is an introduction to rewrite rules in ACL2 and is
 intended for the newcomer to ACL2.  The slightly more experienced user might
 benefit from reading @(see random-remarks-on-rewriting) instead.</p>

 <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 @(see rewrite), @(see definition), and
 @(see meta) rules it knows, in order from the most recently submitted rule to
 the oldest, until it finds one to apply.</p>

 <p>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>")
other
(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 ensures 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 hypotheses 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>")
other
(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 ensure
 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>")
other
(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 a goal first enters
 the waterfall and when a goal is 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 @(see summary).  For a complete list of all the runes in the
 tau database, evaluate @('(get-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>")
other
(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>Many 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='https://www.lulu.com/shop/j-moore-and-panagiotis-manolios-and-matt-kaufmann/computer-aided-reasoning-an-approach/paperback/product-1p52nnn.html'>
 available in
 paperback</a> from Lulu for approximately $22 (as of 2025).  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 @(see pubs::pubs-books),
 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).  If you want a brief tutorial on the
 ACL2 programming language see @(see
 gentle-introduction-to-acl2-programming).</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).  If you want an introduction to the ACL2
 logic work your way through @(see recursion-and-induction).</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>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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>(Is this all that one might want to prove?  It is a good idea to think
 about that question, for any application; an answer for this example is at the
 end of this topic.)</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>

 <p>We conclude this topic by returning to the question posed earlier above: Is
 this all that one might want to prove?  Notice that we didn't prove that every
 element of the given list is indeed an element of the returned list, which
 could be formalized as follows.</p>

 @({
  (thm
    (subsetp x (collect-once x)))
 })")
other
(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>")
other
(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>")
other
(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>We may say that such @(':')@(tsee program)-mode functions have
 invariant-risk.  Because of how the ``aggressive protection'' discussed above
 is implemented, recursive calls of invariant-risk functions are not traced;
 see @(see trace$).</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).  For tools that may help find sources of
 invariant-risk, see @(see community-book)
 @('books/std/system/invariant-risk.lisp').</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>")
other
(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>")
other
(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>")
other
(defxdoc io
  :parents (interfacing-tools 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 (with one
 exception: see @(see read-file-into-string)) 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
 @(tsee print-object$), its more flexible variant @(tsee print-object$+), or
 @('print-object$-preserving-case') (see below; also, @('print-object$-fn')) 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') is defined logically simply to be
 @('read-object'), while the function @('print-object$-preserving-case') and
 macro @(tsee print-object$+) are defined logically simply to be
 @('print-object$').  However, these variants generally do I/O
 differently (except that when the host Lisp is GCL,
 @('print-object$-preserving-case') behaves the same as @('print-object$')).
 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-name') arguments are strings (except for the @(':STRING') case
 discussed below).  ACL2 does not support the Common Lisp type @(tsee
 pathname); rather, the underlying host Lisp will interpret the given string as
 a pathname.  If the string represents a relative pathname, it will be
 elaborated to a full pathname using the connected book directory; see @(see
 cbd).  You can do that elaboration yourself with a directory @('dir') using
 @('(extend-pathname dir file-name state)'); see @(see extend-pathname).</p>

 <p>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$+ (obj channel &key ...) state)
    (print-object$-preserving-case (obj channel state) state)
    (print-object$-fn (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$-fn 17 nil channel state)
             (print-object$-fn '(a b (c d)) nil channel state)
             (er-let*
               ((str1 (get-output-stream-string$
                       channel state
                       nil))) ; keep the channel open
               (pprogn (print-object$-fn 23 nil channel state)
                       (print-object$-fn '((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,
 as does the definition of @(tsee write-list) in @(see community-book)
 @('books/misc/file-io.lisp').</p>")
other
(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'), or if it occurs free in an @(tsee xargs) term associated with
 @(':')@(see measure), @(':')@(see guard), or @(':')@(tsee split-types), 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>")
other
(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 indicating all of the included
 books (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>")
other
(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>")
other
(defxdoc keyword-listp
  :parents (lists keywordp acl2-built-ins)
  :short "Recognizer for true lists of keywords"
  :long "<p>The call @('(keyword-listp x)') return @('t') when @('x') is a
 true-list whose members are all @(see keyword)s, else returns @('nil').</p>")
other
(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.  To list the keys @('ki') and values @('ai') of @('l')
 evaluate @('(evens l)') and @('(odds l)'), respectively.</p>

 @(def keyword-value-listp)")
other
(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)")
other
(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)")
other
(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)")
other
(defxdoc l<
  :parents (term apply$)
  :short "Ordering on naturals or lists of naturals"
  :long "<p>The function @('l<') is a straightforward ordering relation that
 compares two objects, each of which is a natural number or a list of natural
 numbers.  It may be convenient to apply @('lex-fix') to two objects before
 comparing them with @('l<').  Below are the relevant definitions.</p>

 @(def l<)
 @(def lexp)
 @(def d<)
 @(def lex-fix)
 @(def nfix-list)")
other
(defxdoc lambda
  :parents (term apply$)
  :short "Lambda expressions, @('LAMBDA') objects, and @('lambda$') expressions"
  :long "<p>The word ``lambda'' occurs in several different contexts in ACL2.
  When we are being precise our meanings are as outlined below.</p>

  <ul>

  <li>lambda expression -- This phrase is used to describe the syntactic
  entity beginning with the symbol @('lambda') that is allowed to occupy the
  ``function'' position in an ACL2 @(see term).  Lambda expressions are most
  often created when @('let') expressions are translated into their formal
  counterparts.  We provide an example below.</li>

  <li>@('LAMBDA') object -- An ACL2 list constant interpreted as a ``function''
  by @(tsee apply$).  @('LAMBDA') objects may be written in terms by quoting them.
  However, we urge the user to introduce @('LAMBDA') objects into terms by using
  the built-in macro @(tsee lambda$).  We provide examples below.</li>

  <li>@('lambda$') expressions -- These are untranslated terms beginning with
  the macro symbol @('lambda$').  They expand during translation to quoted @('LAMBDA')
  objects.  We provide examples below.</li>

  </ul>

  <p>These three phrases are very similar but mean very different things.  You
  should read carefully when you see us talk about lambda things!
  Unfortunately, we're not always as precise as we might be so you might have
  to disambiguate our usage by context.  If you see places in the documentation
  where you think we've messed up, please bring them to our attention!</p>

  <h3>About Lambda Expressions</h3>

  <p>Consider the function @('odd-evenp'), defined with</p>

  @({
  (defun odd-evenp (x)
    (if (zp x)
        -1
        (let ((ans (odd-evenp (- x 1))))
          (* (+ ans 1) (- ans 1)))))
  })

  <p>Distracting Aside: Can you see why we gave this function this name?  Hint:
  We might have named it ``weird @('evenp').''</p>

  <p>The translated body of @('odd-evenp') is</p>

  @({
  (if (zp x)
      '-1
      ((lambda (ans)
               (binary-* (binary-+ ans '1)
                         (binary-+ '-1 ans)))
       (odd-evenp (binary-+ '-1 x))))
  })

  <p>The syntactic entity in the function position of the term in the false
  branch, namely</p>

  @({
  (lambda (ans)
    (binary-* (binary-+ ans '1)
              (binary-+ '-1 ans)))
  })

  <p>is a lambda expression.</p>

  <p>Lambda expressions are integral to the formal representation of terms.
  They are the formal mechanism by which local variables are introduced and
  thus allow repeated references to intermediate results without causing
  recomputation.  In ACL2 they obey the rules of Common Lisp.  In particular,
  while defining a recursive function it is allowed to call the function
  recursively within the lambda expression, e.g., to temporarily save the value
  of a recursive call for repeated use.  (This is not illustrated by
  @('odd-evenp') where the recursive call is outside of the lambda expression.)
  For more details on the formal representation of ACL2 terms, see @(see
  term).</p>

  <h3>About @('LAMBDA') Objects</h3>

  <p>Prior to Version  8.0 when @('apply$') was introduced, ``lambda
  expression'' was the only phrase the ACL2 developers used mentioning the word
  ``lambda.''  Some Community Books introduced various terms or objects
  mentioning the word but that is beyond the scope of this documentation.
  Because ``lambda'' occurred in no other context before @('apply$') we are not
  confident that every reference to what we are now calling ``lambda
  expressions'' were called by that precise phrase in old documentation.
  If you see a place where we refer to these entities by another phrase, please
  let us know!</p>

  <p>When @(tsee apply$) was introduced, @('LAMBDA') objects became a formally
  supported concept in the ACL2 implementation and we started using
  ``@('LAMBDA') objects'' to refer to them.  A @('LAMBDA') object is generally
  a list, either of the form @('(LAMBDA vars body)') or @('(LAMBDA vars dcl
  body)').  There are additional restrictions on @('vars'), @('dcl'), and
  @('body') that we discuss later.  But @('apply$') treats any @('consp')
  object and tries to extract those components by rudimentary pattern matching.
  An example of a @('LAMBDA') object is the list of length three
  @('(LAMBDA (x) (BINARY-+ '1 X))').</p>

  <p>Generally speaking when @('LAMBDA') objects occur in translated terms they
  are @('quote')d, as in</p>

  @({
  (collect$ '(LAMBDA (X) (BINARY-+ '1 X)) lst)
  })

  <p>To highlight the fact that these objects are constants, we try to write
  them in UPPERCASE and @('typewriter') font in this documentation.  For the
  same reason, we generally write ``@('LAMBDA') object'' rather than ``lambda
  object.''</p>

  <p>But of course there's no difference between the symbol @('LAMBDA') and the
  symbol @('lambda').  Furthermore, @('LAMBDA') objects need not be quoted.
  From a logical perspective they could just be consed up because they are just
  ordinary ACL2 list constants.  Their ``lambda'' status comes from being
  treated as functions by @('apply$').  So one could write</p>

  @({
  (collect$ (list 'lambda '(x) '(binary-+ '1 x)) lst)
  })

  <p>and we would say that the value of the term in the first argument of
  @('collect$') is a @('LAMBDA') object.</p>

  <p>Beware, however, that consing up @('LAMBDA') objects defeats the @(see
  ilk) analysis in @(tsee defwarrant) and the @(see tame)ness analysis of
  @('apply$') and hence prevents functions containing such terms from being
  @('apply$')d.</p>

  <p>According to the definitional axiom defining @(tsee apply$), any object
  satisfying @('consp') is treated as a @('LAMBDA') object.  @('Apply$') uses
  ``accessor'' functions to extract the ``formals'' and ``body'' of the object
  and proceeds to @(tsee ev$) the body in an alist binding the formals.  But
  @('ev$') insists that the expression object being evaluated be @(see tame) or
  else assigns it a default value.  This insistence on tameness is due to
  fundamental logical reasons; otherwise, @('apply$') would allow us to prove
  @('NIL').  So axiomatically @('apply$') operates as ``naively expected'' only
  on @('tamep-lambdap') objects.  One consequence of this, which we expect will
  be a minor inconvenience, is that unlike ACL2's lambda expressions
  @('apply$')'s @('LAMBDA') objects, when used in definitions of new functions,
  may not include recursive calls of the function being defined because they
  fail the tameness test.</p>

  <p>But wait!  There's more.  Execution efficiency of @('apply$') imposes some
  non-logical restrictions.  These restrictions come from ACL2's execution
  story with respect to Common Lisp, and from the Common Lisp compiler.  To
  execute @('LAMBDA') objects most efficiently they must be well-formed, which
  is a concept even stronger than tameness.  Among other requirements,
  well-formed @('LAMBDA') objects obey the ACL2 and Common Lisp rules on
  variable names (not every symbol is a legal variable), on the use of free
  variables, on the body being a fully translated formal term, that the
  declarations, if any, be meaningful to the Common Lisp compiler, etc.  You
  can read about well-formedness in @(tsee well-formed-lambda-objectp) if you
  want, but we don't encourage beginners to go there!</p>

  <p>Note: Even well-formedness is not enough to guarantee execution of
  compiled code.  The @('LAMBDA') object must also be guard verified (see
  @(tsee verify-guards) for a discussion) and its guard must be satisfied by
  the arguments to which it is applied.</p>

  <p>Note: A peculiar aspect of @('LAMBDA') objects is that they can be written
  as legal ACL2 constants <i>before</i> they are well-formed @('LAMBDA')
  objects, e.g., by referring to undefined functions, @(':program') mode
  functions, unbadged functions, etc.  They are, after all, just arbitrary
  quoted objects and any value in ACL2 can be quoted.  An ill-formed
  @('LAMBDA') object can <i>become</i> well-formed if the world is
  appropriately extended, e.g., the appropriate @('defun')s or
  @('defwarrant')s are made.  Perhaps worse, they can be well-formed and then
  <i>become</i> ill-formed by an undo.  So at runtime @('apply$') has to check
  that the function symbol or @('LAMBDA') object is appropriate.  There is a
  sophisticated cache behind the execution machinery for @('LAMBDA') objects in
  the evaluation theory.  See @(tsee print-cl-cache).</p>

  <h3>About Lambda$ Expressions</h3>

  <p>Rather than force users to type well-formed @('LAMBDA') objects as quoted
  constants, ACL2 provides a macro allowing you to enter @('LAMBDA') objects by
  typing something that looks like a lambda expression but which is properly
  translated and generates well-formed results (or causes a translation
  error).</p>

  <p>That macro -- which is not really a defined macro but is built into ACL2's
  translation mechanism -- is called @(tsee lambda$) and uses of it in terms
  are called ``@('lambda$') expressions.''  @('Lambda$') expressions may only be
  used in argument slots of @(see ilk) @(':FN').</p>

  <p>An example of a @('lambda$') expression is the first argument of
  @('collect$') in</p>

  @({
  (collect$ (lambda$ (x) (+ 1 x)) lst)
  })

  <p>That @('lambda$') expression essentially translates to the quoted
  well-formed @('LAMBDA') object</p>

  @({
  '(LAMBDA (X) (BINARY-+ '1 X))
  })

  <p>Note that the body is fully translated, unlike its appearance in the
  @('lambda$') expression.  We say ``essentially'' because @('lambda$') always
  add a @('(DECLARE (IGNORABLE v1 ... vn))') that includes every formal.  In
  addition, except when translating in theorems, @('lambda$') tags the
  translated body with a @(tsee RETURN-LAST) expression to indicate it came
  from a @('lambda$').  Despite these differences, the meaning of the
  translated @('lambda$') is the simple quoted @('LAMBDA') object shown.</p>

  <p>@('Lambda$') expressions never appear in a fully translated term.  All the
  @('lambda$') objects will have been translated into quoted @('LAMBDA')
  objects.</p>

  <p>The body of a @('lambda$') expression must return a single value that is
  neither a @(see stobj) nor a @(see df).  The following example illustrates
  this point.</p>

  @({
  (defun$ f1 (x)
    (declare (xargs :guard t))
    (mv x x))

  ; ERROR!  The body of the lambda$ returns two values.
  (defun f2 (y)
    (declare (xargs :guard t))
    (apply$ (lambda$ (x) (f1 x))
            (list y)))

  ; Succeeds.
  (defun f2 (y) (declare (xargs :guard t))
    (apply$ '(lambda (x) (f1 x))
            (list y)))
  })

  <p>Finally, to see how a @('lambda$') expression translates, see @(tsee
  translam).</p>")
other
(defxdoc lambda$
  :parents (apply$)
  :short "Lambda object constructor for use with @('apply$')"
  :long "<p>@('Lambda$') is a built-in ACL2 ``macro'' that allows you to enter
  well-formed fully-translated quoted @('LAMBDA') objects in argument positions
  of ilk @(':FN').  We urge you to use @('lambda$') instead of trying to type
  quoted @('LAMBDA') objects meant for use by @('apply$').  We explain and
  document @('lambda$') below.</p>

  <p>Intuitively, a quoted @('LAMBDA') object is a quoted constant like</p>

  @({
  '(LAMBDA (X) (BINARY-+ '1 X))
  })

  <p>e.g., a quoted constant beginning with the symbol @('LAMBDA') and listing
  some formal variables, possibly some declarations, and a fully translated
  body satisfying various rules.  @(tsee Apply$) can handle quoted @('LAMBDA')
  objects provided they have the right basic shape and all the listed formals
  are symbols and the bodies are @(see tame).  But it is difficult to type
  fully translated bodies and, for runtime efficiency, it is important that the
  quoted @('LAMBDA') objects satisfy additional (logically unnecessary)
  well-formedness restrictions allowing faster guard checking and
  compilation.</p>

  <p>One should strive to always enter ``well-formed @('LAMBDA') objects.''
  The details of well-formedness may be found in @(tsee
  well-formed-lambda-objectp) but our hope is that mastering those details is
  unnecessary because ACL2 provides a built-in ``macro,'' @('lambda$'), for
  constructing quoted well-formed @('LAMBDA') objects.  We urge you to use
  @('lambda$') instead of typing quoted @('LAMBDA') objects!  That is, write
  @('(lambda$ (x) (+ 1 x))') instead of @(''(LAMBDA (X) (BINARY-+ '1 X))').</p>

  <p>@('Lambda$') <i>terms may only appear in argument slots of ilk</i>
  @(':FN')!</p>

  <code>
  Examples:
  (lambda$ (x y) (append x (list y)))

  (lambda$ (n lst str)
           (declare (type integer n)
                    (type string str)
                    (xargs :guard (and (posp n)
                                       (true-listp lst)
                                       (&lt; (- n 1) (length lst)))))
           (nth (- n 1) lst))

  General Form:
  (lambda$ vars dcl* body)
  </code>

  <p>where the @('lambda$') expression occurs in an argument position of ilk
  @(':FN'), @('vars') is a list of distinct variable names, @('dcl*') is zero
  or more @('DECLARE') forms as described below, and @('body') is a term
  returning the appropriate number of values, which is currently always 1
  except when used in the translation of an expression of the form @('(loop$
  ... DO ...)').  @('Body') must satisfy the same restrictions one would expect
  in a non-recursive @(tsee defun) event with the same formals, declarations
  and body.  In particular, @('body') should contain no free variables other
  than those listed in @('vars').  @('Lambda$') always adds a declaration that
  every formal is ignorable and, hence, we prohibit you from adding @('ignore')
  or @('ignorable') declarations in the @('lambda$') expression itself.
  @('Lambda$') expands to a well-formed quoted @('LAMBDA') object or else
  causes a translate-time error.</p>

  <p>The allowed @('DECLARE') forms in @('lambda$') are @('type') and
  @('xargs').  Furthermore, the only @(tsee xargs) keywords allowed are
  @(':guard') and @(':split-types').  The other @('XARGS') keywords, such as
  @(':measure'), @(':hints') or @(':guard-hints'), play no role.</p>

  <h3>About @('Lambda$')s and Prover Output</h3>

  <p>The translated form of a @('lambda$') expression is a quoted @(tsee
  lambda) object.  For example, @('(collect$ (lambda$ (x) (+ 1 x)) lst)')
  translates to</p>

  @({
  (COLLECT$ '(LAMBDA (X)
                   (DECLARE (IGNORABLE X))
                   (RETURN-LAST 'PROGN
                                '(LAMBDA$ (X) (+ 1 X))
                                (BINARY-+ '1 X)))
            LST)
  })

  <p>The @('lambda$') has been replaced by a quoted @('lambda').</p>

  <p>The prover tries to print each quoted @('lambda') object (that occurs
  an argument position of @(see ilk) :@('FN')) as a @('lambda$')
  expression that is (provably) functionally equal (see @(tsee fn-equal)) to
  the original @('lambda') object assuming the necessary warrants.  If the
  quoted @('lambda') object was produced by the expansion of a @('lambda$')
  expression and has not been simplified by subsequent rewriting, it will print
  as the original @('lambda$') expression.  This can be unfortunate if the
  original @('lambda$') expression was itself produced by a macro and contains
  logically irrelevant (but operationally important) tags.  This phenomenon
  occurs most often when @(tsee do-loop$)s are involved.</p>

  <p>Furthermore, since you are allowed to type in quoted @('lambda') objects
  directly, you may &mdash; or may not &mdash; see them printed by the prover
  as @('lambda$') expressions, depending on whether a suitable @('lambda$') is
  found.  If a quoted @('lambda') object contains a reference to a function
  symbol for which no @(tsee warrant) has been issued there is probably no
  provably equivalent @('lambda$').</p>

  <p>The main lessons here are</p>

  <ul>

  <li>you should use @('lambda$') rather than quoted @('lambda') objects in
  your prover input,</li>

  <li>you should make sure to warrant every user-defined function in your
  @('lambda$') expressions, and</li>

  <li>if you see a quoted @('lambda') object rather than a @('lambda$')
  expression in your prover output, that quoted @('lambda') object probably
  involves unwarranted symbols which will make it impossible to prove anything
  interesting about it.</li>

  </ul>

  <p>If you do not want the prover output to give special treatment to quoted
  @('lambda') objects in :@('FN') slots, do</p>

  @({
  (defattach-system (untranslate-lambda-object-p
                    constant-nil-function-arity-0))
  })

  <p>With this attachment, the prover will print all quoted @('lambda') objects
  as it would any other quoted constant.  You will see what is actually there.
  One drawback is that the resulting formulas cannot always be read back in
  and translated because of a prohibition on ``counterfeiting'' expansions of
  @('lambda$').  See @(see gratuitous-lambda-object-restrictions).</p>

  <h3>About Guard Verification of Lambda Objects</h3>

  <p>Quoted @('LAMBDA') objects, whether produced by hand (don't!) or by
  @('lambda$') may have guards.  If the @('LAMBDA') object is well-formed its
  guard plays the same role the guard of a defined function symbol plays when
  the object is @('apply$')d.  If the guard can be verified to imply the guards
  of the body (which we call <i>guard verification</i>), and if the guard holds
  of the actuals to which the object is applied (which we call <i>guard
  checking</i>), a compiled version of the object is run.  Otherwise, depending
  on how @(tsee set-guard-checking) has been configured, either an error is
  signaled or the object is interpreted under the axioms defining @('apply$')
  and @('ev$').  @('Apply$') caches its investigations into guard
  verification (but not guard checking) and compilation.  We discuss the cache
  in @(tsee print-cl-cache).</p>

  <p>When a guarded quoted @('LAMBDA') object is used in a @(':FN') slot of a
  function definition, its guards are verified as part of the guard
  verification step of @('defun') or @('verify-guards').  If that guard
  verification fails, checkpoints will be printed and you can use
  @(':guard-hints') or @(':hints') in the @('defun') or @('verify-guards')
  events to supply the necessary guidance.  When successful, the guard verified
  @('LAMBDA') objects in the @('defun') are recorded in the cache.</p>

  <p>But unlike defined function symbols, whose guards may be verified at
  @('defun')-time or at @('verify-guards')-time, quoted @('LAMBDA') expressions
  may be introduced without an associated event.  For example, the user may
  simply type</p>

  <code>
  ACL2 !&gt;(apply$ (lambda$ (x)
                          (declare (type (satisfies natp) x))
                          (* x x))
                 '(5))
  </code>

  <p>giving @('apply$') a @('LAMBDA') object never before seen.</p>

  <p>So @('apply$') must be ready to verify the guards of a quoted @('LAMBDA')
  object before attempting to apply it.  This is in contrast to what happens
  when @('apply$') is given a quoted function symbol.  (@('Apply$') can just
  look up whether a function symbol has been guard verified.)</p>

  <p>To try to verify the guards of a quoted @('LAMBDA') expression, @('apply$')
  limits itself to tau reasoning (see @(see introduction-to-the-tau-system)).  The
  idea is not to spend too much time making the decision as to whether compiled code
  can be used or not.  In addition, we don't want top-level evaluation, as shown
  in the user type-in above, to provoke full-blown theorem proving.</p>

  <p>Interpreting small quoted @('LAMBDA') objects can be done relatively
  quickly.  After all, when the interpreter reaches a guard verified function
  symbol inside the @('LAMBDA') body it runs compiled code.  It's only the body
  itself that is interpreted.</p>

  <p>But the tau system is pretty weak and so will be unable to verify some
  non-trivial guard conjectures, which will mean the @('LAMBDA') object is
  interpreted.  If the @('LAMBDA') object is very large or is being being used
  often, e.g., to map over a large object and check some property, you might
  really want to invest the time to verify its guards.  This can be done with
  @(tsee verify-guards), which as of Version 8.1 takes @('LAMBDA') objects and
  @('lambda$') terms and updates the cache.  E.g.,</p>

  @({
  (verify-guards
    (lambda$ (x)
             (declare (type (satisfies natp) x))
             (* x x)))
  })

  <p>While this functionality is available to you, deciding that you need to
  use it is problematic.  @('Apply$') prints no warning that it has failed to
  verify the guards of a @('LAMBDA') object and is running interpreted code.
  However, the utility @(tsee print-cl-cache) provides basic information about
  the cache and its documentation may help you discover which @('LAMBDA')
  objects in use are unverified.</p>")
other
(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, @('l').  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)")
other
(defxdoc last-cdr
  :parents (lists acl2-built-ins)
  :short "The last @(tsee cdr) of a list"
  :long "<p>@('(Last-cdr x)') is @('x') if @('x') is an @(tsee atom), and
 otherwise is the last @(tsee cdr) of a list.  Here are examples.</p>

 @({
  ACL2 !>(last-cdr '(a b . c))
  C
  ACL2 !>(last-cdr '(a b c))
  NIL
 })

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

 @(def last-cdr)")
other
(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).</p>

 <p>The @(see summary) printed for an @(see event) typically includes a line
 showing the prover steps counted, for example as follows.</p>

 @({
 Prover steps counted:  7240
 })

 <p>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 @(see summary) would normally be printed.  Note that
 the value of @('(last-prover-steps state)') is updated for all @(see events),
 and more generally, for all forms that are set up to print a @(see summary),
 such as calls of @(tsee thm) or @(tsee certify-book) &mdash; regardless of
 whether or not summary 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, e.g., with @('(thm (equal x x))');
 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>Note that the ``most recently completed event'' in this sense includes
 compound events.  Consider the following example.</p>

 @({
 (progn (thm (equal (append (append x y) z) (append x y z)))
        (thm (equal (car (cons x y)) x)))
 })

 <p>The summaries show (in some ACL2 versions, at least) 435 steps for the
 first call of @('thm') and 7 steps for the second call of @('thm'), with 442
 steps thus shown in the summary for the entire @('progn') call.  Subsequent
 evaluation of @('(last-prover-steps state)') returns 442.  On the other hand,
 suppose that @('(set-prover-step-limit 440)') is evaluated immediately before
 evaluating the @('progn') call above.  Then the summaries show the following
 for the two @('thm') calls and the @('progn') call, in order as follows.</p>

 @({
 Prover steps counted:  435
 Prover steps counted:  More than 5
 Prover steps counted:  More than 440
 })

 <p>Since the most recently completed event is the @('progn') call, then
 @('(last-prover-steps state)') returns -440.</p>

 <p>We conclude with two remarks for advanced users who wish to invoke
 @('last-prover-steps') in the development of utilities that track prover
 steps.</p>

 <p>Remark 1.  Suppose that you want to write a utility that takes some action
 based on the number of prover steps performed by the first event that is
 generated within a sequence of events, 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 ...))
 })

 <p>Remark 2.  It is possible to write utilities that are treated as @(see
 events) for purposes of the discussion above; that is, their calls can be
 followed by evaluating @('(last-prover-steps state)') as described above.  For
 an example of how to do this using the ACL2 system macro
 @('with-ctx-summarized'), see the implementation of @(tsee prove$) in @(see
 community-book) @('books/tools/prove-dollar.lisp').</p>")
other
(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                ...      ; directory spec if standard-oi is a string
     :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
     :useless-runes      ...      ; :write/:read/:read?/n/-n/nil
                                  ;   (-100 &lt; n &lt; 0 or 0 &lt; n &lt;= 100)
                                  ;   (see @(see useless-runes))
     :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-always-skip-top-level-locals      ; 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
 generally called ``@('ld') specials'' (after the Lisp convention of calling a
 variable ``special'' if it is referenced freely after having been bound).  (We
 say ``generally'' because technically, @('current-package') and
 @('useless-runes') are not considered to be @('ld') specials.)</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), @(see
 useless-runes), @(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 is provided and not @('nil'), we look up @(':dir') just as
 is done for @(tsee include-book); also see @(tsee add-include-book-dir),
 @(tsee add-include-book-dir!), and @(tsee project-dir-alist).  Thus a suitable
 directory is prepended to create the filename.  Note that @('standard-oi')
 must be a string that 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 @(see community-books) library.  (Of
 course, for certified @(see books) you should almost always use @(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).  If you want to load a list of forms, then consider prepending a call of
 @(tsee set-cbd) to that list rather than using @(':dir'), which is not
 supported when @('standard-oi') is a list.</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>(Technical Aside.  Some special handling takes place when @('ld') is called
 in the scope of @(tsee local), as in @('(local (ld <C>))') for a command,
 @('<C>').  In that case, after @('<C>') is evaluated, then if the result is an
 @(see error-triple) and @('<C>') is not already of the form @('(local <C0>)'),
 then when the command is stored in the ACL2 @(see world) it is stored as
 @('(local <C>)') instead of @('<C>').  See @(see ld-history) for a similar
 treatment of local commands.  End of Technical Aside.)</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')), @(':missing-input') (meaning that the specified input file is
 missing, in the case that keyword @(':ld-missing-input-ok') has a non-@('nil')
 value so that an error is avoided), 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>")
other
(defxdoc ld-always-skip-top-level-locals
  :parents (ld)
  :short "Determines whether @(tsee ld) skips @(tsee local) top-level forms"
  :long "<p>@('Ld-always-skip-top-level-locals') is an @(tsee ld) special (see
 @(see ld)).  The accessor is @('(ld-always-skip-top-level-locals state)') and
 the updater is @('(set-ld-always-skip-top-level-locals val state)').  The
 value of @('ld-always-skip-top-level-locals') must be either @('nil') or
 @('t').  The initial value of @('ld-always-skip-top-level-locals') 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-always-skip-top-level-locals') is one of them.  When the value is
 @('t'), @(tsee local) @(see events) are skipped when they are at the top level
 in the following sense: they are not evaluated in the scope of either a call
 of @(tsee certify-book), @(tsee include-book), or @(tsee encapsulate), or else
 during @(tsee make-event) expansion.</p>")
other
(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').  Later in this topic we discuss another case in which an error
 is said to have occurred: when the value component of an error triple is of
 the form @('(:STOP-LD . x)').</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)').  If @('ld-error-action') is of
 the form @('(:EXIT N)'), then ACL2 quits with exit status @('N').
 Otherwise (i.e., when @('ld-error-action') is @(':RETURN'), @(':RETURN!'), or
 @(':ERROR')), 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>")
other
(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>")
other
(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>")
other
(defxdoc ld-history
  :parents (ld history)
  :short "Saving and querying command history"
  :long "<p>See @(see ld) for background on the ACL2 read-eval-print loop.  The
 present topic pertains to a history kept for commands issued to that loop,
 which we call an ``ld-history'' (pronounced ``ell dee history'').  Here are
 some things to keep in mind when reading this topic.</p>

 <ul>

 <li>Each entry in the history includes the input command, the value returned,
 and other information, as explained further below.</li>

 <li>This is about commands, not events: that is, we are concerned with forms
 that are submitted for evaluation to the top-level loop.  See @(see
 command).</li>

 <li>An entry is saved for every command submitted by the user, even if it
 doesn't change the ACL2 @(see world) &mdash; e.g., @('(+ 3 4)') &mdash; and
 even if it undoes commands &mdash; e.g., @(':')@('ubt').</li>

 <li>Keyword commands are turned into s-expressions before saving an entry; see
 @(see keyword-commands).  For example, the input @(':ubt :x') is stored in an
 entry as the input @('(ubt ':x)').</li>

 <li>When an entry is saved for a command @('C') that is evaluated in the
 context of a call of @(tsee local), where @('C') evaluates to an @(see
 error-triple), then @('C') is stored in the entry as @('(local C)') unless
 @('C') is already a call of @('local').  (Technical Aside: This behavior
 supports local @(see portcullis) commands.)</li>

 <li>The ld-history saves entries not only for commands issued in the original
 top-level loop, but also for commands issued in (recursive) calls of @(tsee
 ld) &mdash; but not during @(tsee make-event) expansion.</li>

 <li>Entries are generally saved even when there are errors.  However, entries
 are not saved for commands that exit with raw Lisp errors.</li>

 </ul>

 <p>Also see @(see community-books) file @('books/demos/ld-history-input.lsp')
 for examples.  The output from calling @(tsee ld) on that file (by calling the
 @(tsee run-script) tool in @('books/demos/ld-history-book.acl2')) is in @(see
 community-books) file @('books/demos/ld-history-log.txt').</p>

 <p>The ld-history is a stack, represented as a list with the most recent
 commands at the front.  But by default ACL2 is in <i>single-entry mode</i>,
 where the list is kept at length 1: an entry is saved in the ld-history only
 for the most recent command, and the previous entry is discarded.  We now
 describe relevant utilities, including one that can switch to
 <i>multiple-entry mode</i>, where all entries are kept until a utility is
 called explicitly to discard old entries.  Note that the mode is determined by
 the length of the ld-history: single-entry mode when length 1, multiple-entry
 mode when length 2 or more.</p>

 <ul>

 <li>@('(ld-history state)')<br/>

 This utility returns a list of structures, denoted ``ld-history entries'',
 with the most recent one first.  By default, this list has length 1, but that
 can be changed; see @('adjust-ld-history') below.  Each entry in the list is
 recognized by the following predicate.  <b>NOTE</b>: This query is evaluated
 before the ld-history stored in the ACL2 state is updated with a new entry,
 based on the current command; so the previous command will be at the top of
 the returned stack, not the current command.  (In particular, submitting the
 form @('(ld-history state)') at the ACL2 prompt does not put that form at the
 front of the returned list.)</li>

 <li>@('(weak-ld-history-entry-p x)')<br/>

 This function returns @('t') if @('x') has the shape of an entry in the
 ld-history list, else @('nil').</li>

 <li>Here are accessors for an ld-history entry, which we think of as returning
 its fields.  The formal parameter @('entry') below is an entry in (i.e.,
 member of) @('(ld-history state)'); an example call is thus
 @('(ld-history-entry-input (car (ld-history state)))').<br/>

 <ul>

 <li>@('(ld-history-entry-input entry)')<br/>

 The user input</li>

 <li>@('(ld-history-entry-error-flg entry)')<br/>

 Non-@('nil') when there was an error translating the user input</li>

 <li>@('(ld-history-entry-stobjs-out/value entry)')<br/>

 When @('(ld-history-entry-error-flg entry)') is @('nil'), this is a cons whose
 @('car') is the @(see stobjs-out) &mdash; a list whose length is the number of
 values returned, with @('nil') in each position except when occupied by a
 symbol indicating a returned @(see stobj) for that position &mdash; and whose
 @('cdr') is the returned value in the single-value case, but is the list of
 returned values in the @(see multiple-value) case.</li>

 <li>@('(ld-history-entry-stobjs-out entry)')<br/>

 When @('(ld-history-entry-error-flg entry)') is @('nil'), this is the
 stobjs-out as described above; otherwise this is @('nil').</li>

 <li>@('(ld-history-entry-value entry)')<br/>

 When @('(ld-history-entry-error-flg entry)') is @('nil'), this is the value or
 values as described above; otherwise this is @('nil').</li>

 <li>@('(ld-history-entry-user-data entry)')<br/>

 This is @('nil') by default.  However, code can be provided to compute this
 field, as discussed below.</li>

 </ul></li>

 <li>@('(adjust-ld-history x state)')<br/>

 @('X') is @('t'), @('nil'), or an integer.  The result is an @(see
 error-triple) @('(mv nil value state)'), where @('value') and the effect are
 as follows, and where if there is no change (i.e., the effect is a no-op) then
 @('value') is @('(:no-change :length N)') where @('N') is the current length
 of the ld-history.

 <ul>

 <li>@('T'):<br/>

 Change to multiple-entry mode, where an entry is saved for every command, not
 just the most recent command.  There is no change if already in multiple-entry
 mode; otherwise the returned @('value') is @('(:saving-ld-history t)').</li>

 <li>@('NIL'):<br/>

 Change to single-entry mode, where an entry is saved only for the most recent
 command.  There is no change if already in single-entry mode; otherwise the
 returned @('value') is @('(:saving-ld-history nil)'), and all old entries will
 be discarded (to produce a single-element ld-history).</li>

 <li>Positive integer @('k'):<br/>

 Replace the current ld-history by its first @('k') entries, except there is no
 change if in single-entry mode or if @('k') is not less than the length of the
 current ld-history.  Note that by ``current ld-history'' we refer to the
 ld-history in effect at the time @('adjust-ld-history') is invoked, which does
 not include the current command being evaluated.  (Thus, even if @('k') is 1,
 multiple-entry mode will be preserved: the ld-history will have 2 entries
 immediately after the current command completes.)  The returned @('value') is
 @('(:ld-history-truncated :old-length LEN :new-length k)'), where @('LEN') is
 the length of the current ld-history before the change.</li>

 <li>Negative integer @('-k'):<br/>

 This is intended to specify removal of the oldest @('k') entries from the
 current ld-history.  Thus, it is treated identically to argument @('k2') where
 @('k2') is the sum of @('-k') and the length of the current ld-history, but
 only if that sum is positive; else there is no change.  For example, suppose
 that @('-k') is -3.  If the current ld-history, @('h'), has length 2 or 3,
 then there is no change; but if @('h') has length 10, then it is to be
 replaced by @('(take 7 h)') and the length will actually thus be 8 after the
 current command completes.</li>

 </ul>

 </li></ul>

 <p>Note that a call of @('adjust-ld-history') is not an @(see event) that can
 be placed directly in @(see books) or @(tsee encapsulate) forms.</p>

 <p>Remark.  If @('(adjust-ld-history n state)') is evaluated while in
 multiple-entry mode, where n is a positive integer less than the current
 length of the ld-history, then the new ld-history after returning to the
 prompt will have length @('n+1').  That's essentially because it will have
 length @('n') immediately after that call of @('adjust-ld-history') is
 evaluated, and then a new entry for the current command (which could be that
 call itself, if that's what was submitted at the prompt) will be pushed onto
 the ld-entry just before returning to the prompt.  We say ``essentially''
 because there is a Special Case: when @('n') is 1 then a 2-element list of
 entries @('(e1 e2)') is created where @('e2') has fields that are all
 @('nil'); then when the new entry @('e') is pushed onto the ld-history,
 @('e2') is dropped so that the new ld-history is @('(e e1)').  This
 special-case trick is also used in multiple-entry mode when @('n') is @('-k')
 where @('k') is one less than the length of the current ld-history, since that
 is treated the same as @('(adjust-ld-history 1 state)'); and this trick is
 also used when @('(adjust-ld-history t state)') switches from single-entry
 mode to multiple-entry mode.  End of Remark.</p>

 <p>Finally we discuss the user-data field of a ld-history entry, which (as
 noted above) has default @('nil').  It is accessed using
 @('(ld-history-entry-user-data entry)').  It is set automatically when
 the ld-history is extended with a new entry: the function call
 @('(set-ld-history-entry-user-data input error-flg stobjs-out/value state)'),
 is executed where the actuals are the other fields of the entry as indicated,
 e.g., the first actual is the input field of the new entry
 (as returned by the function, @('ld-history-entry-input')).  Although
 @('set-ld-history-entry-user-data') returns @('nil') by default, this can be
 changed by providing your own function with a @(':')@(tsee guard) of @('t')
 and the same formal parameters (which however may be renamed, other than
 @('state')).  To make that change, define a function, which here we call
 @('my-user-data'), and then attach it to @('set-ld-history-entry-user-data'),
 as follows.</p>

 @({
 (defun my-set-user-data (input error-flg stobjs-out/value state)
   (declare (xargs :guard t))
   ...)
 (defattach-system set-ld-history-entry-user-data my-set-user-data)
 })

 <p>The following example illustrates how to store the length of the ACL2 @(see
 world) in the user-data.  Note that the @(see world) present in the @(see
 state) at the time the user-data is set, computed as @('(w state)'), is almost
 the final world produced by the command &mdash; it is missing just one triple,
 a so-called command marker.</p>

 @({
 (defun my-world-length (input error-flg stobjs-out/value state)
   (declare (xargs :guard t :stobjs state)
            (ignore input error-flg stobjs-out/value))
   (len (w state)))

 (defattach-system set-ld-history-entry-user-data my-world-length)
 })

 <p>A subsequent inspection of the stored user-data shows the length of the
 current world, for example as follows.</p>

 @({
 ACL2 !>(ld-history-entry-user-data (car (ld-history state)))
 125914
 ACL2 !>
 })

 <p>Notice that we used @(tsee len), not @(tsee length), since the @(':')@(tsee
 guard) specified for our function needs to be @('t').  Alternative
 definitions, which however are less efficient, are as follows.</p>

 @({
 (defun my-world-length (input error-flg stobjs-out/value state)
   (declare (xargs :guard t :stobjs state)
            (ignore input error-flg stobjs-out/value))
   (and (true-listp (w state))
        (length (w state))))

 (defun my-world-length (input error-flg stobjs-out/value state)
   (declare (xargs :guard t :stobjs state)
            (ignore input error-flg stobjs-out/value))
   (ec-call (length (w state))))
 })

 <p>Here is how to restore the original behavior, i.e., the default where
 the user-data is set to @('nil').</p>

 @({
 (defattach-system set-ld-history-entry-user-data
                   set-ld-history-entry-user-data-default)
 })

")
other
(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>")
other
(defxdoc ld-missing-input-ok
  :parents (ld)
  :short "Determine whether @(tsee ld) causes an error for a missing file"
  :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)').  The value of
 @('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>")
other
(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 signaled, @(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>")
other
(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)).  (There is actually a value that may on
 rare occasions be set by the ACL2 system, @(':illegal-state'); we ignore that
 value here, but the curious reader is welcome to see @(see illegal-state).)
 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 @(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>")
other
(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>")
other
(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,
 @('fn'), and install it with @('(set-ld-prompt 'fn state)').  However, a trust
 tag must be active (see @(see defttag)) when you set @('ld-prompt') to other
 than @('t') or @('nil') (with two exceptions: the functions @('brr-prompt')
 and @('wormhole-prompt'), which print the prompt in the @(see break-rewrite)
 loop and the general @(see wormhole) loop, respectively).</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>")
other
(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>")
other
(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, @('f'), that is called in the
 body of another function, @('g'), may not cause the new version of @('f') to
 be called by @('g').  In addition, for some Lisps, in particular GCL Version
 2.7.0 or later, the return type @('TP') inferred for the original definition
 of @('f') might cause mishandling of the return value from @('f') as @('g')
 still expects that value's type to be @('TP').  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>")
other
(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 skips all proofs, which of course can render the system 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 ``@(see
 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>User-defined tools may temporarily modify the global setting of
 @('ld-skip-proofsp'); for example, see @(see remove-hyps).</p>

 <p>We close by reminding the user that ACL2 is potentially unsound if
 @('ld-skip-proofsp') is set by the user.  Indeed, direct setting of
 @('ld-skip-proofsp') is illegal within a book (except during @(tsee
 make-event) expansion).  We provide access to it simply to allow
 experimentation and rapid reconstruction of lost or modified logical @(see
 world)s.</p>")
other
(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 system books
 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 @('#\b') is the system books directory, @('#\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>")
other
(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'').  See
 @(tsee set-constraint-tracking) for help figuring out where subgoals generated
 by @(':functional-instance') hints came from.</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').  (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.)  Note that unlike normal @(see
 functional-instantiation), here there is no proof obligation.  However, the
 restriction applies from (5) above that the functions @('fi') are
 instantiable; when that fails, then the replacement of each @('fi') by @('gi')
 will not take place.</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 simplify)'),
 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 @('simplify') is
 @(':limited'), which enables certain simplifications as documented elsewhere;
 see @(see gthm).  Otherwise @('simplify') should be @('nil'), to avoid all
 such simplification.  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, by default, 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) and @(see guard-simplification).  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 simplify guard-debug (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>")
other
(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)")
other
(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)")
other
(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.  In ACL2 the only @(tsee declare)
forms allowed for a @('let') form are  @('ignore'), @('ignorable'), and
@('type').  See @(see declare).</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 @('vari') 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>")
other
(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>")
other
(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)")
other
(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 the term @('(rel lhs rhs)') is a
 call of one of the inequality relations @(tsee <), @(tsee <=), @(tsee >), or
 @(tsee >=); the negation of such a call; a call of @(tsee =) or @(tsee equal);
 or a negated call of @(tsee /=).  Note that we refer to all of these terms as
 ``inequalities'' below, even the equalities.  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 (as well as macroexpansion, which removes calls of
 @(tsee <=), @(tsee >), and @(tsee >=)).</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>

 </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
 after replacing, where possible based on the @(see current-theory), ground
 subterms (those that have no free variables) with their values.</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.  Note that
 the notion of ``enough variables'' in (b) is affected by hypotheses that are
 calls of @('bind-free'); see @(see bind-free).</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>

 <p>We conclude by noting that linear rules are useless when all of the
 polynomial's terms are provably non-numeric.  If ACL2 determines that to be
 the case for one or more of the conclusions, then it causes an error, except
 when @(':trigger-terms') is supplied explicitly by the user.</p>")
other
(defxdoc linear-arithmetic
  :parents (linear)
  :short "A description of the linear arithmetic decision procedure"
  :long "<p>ACL2 incorporates a rational linear arithmetic decision procedure.
 When the ACL2 prover attempts to simplify a goal, it first constructs a data
 structure, called the ``linear pot list'' (see @(see linear)), that records
 inequalities derived from the current goal, as an early step in the
 simplification process.  The linear pot list is constructed as follows: first,
 it is seeded with equalities and inequalities about arithmetic terms occurring
 in the goal to be proved; then, it is extended by instantiating @(':')@(tsee
 linear) lemmas about terms already in the pot list.  The resulting pot list is
 then supplied to the decision procedure when the rewriter is trying to
 establish or refute an arithmetic equality or inequality.  This happens, for
 example, when an inequality occurs as a hypothesis of a rule being applied by
 the rewriter.  (For discussion of the rewriter in general, see @(see
 introduction-to-rewrite-rules-part-1) and @(see
 introduction-to-rewrite-rules-part-2).)</p>

 <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>")
other
(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>If a call of @('list') results in an error due to too many arguments,
 consider using @(tsee list$).</p>

 <p>@('List') is defined in Common Lisp.  See any Common Lisp documentation for
 more information.</p>

 @(def list)
 @(def list-macro)")
other
(defxdoc list$
  :parents (lists acl2-built-ins)
  :short "Build a list"
  :long "<p>@('List$') is a macro that is virtually interchangeable with @(tsee
 list).  The only difference is that when the host Lisp is @(see GCL) with GCL
 version at least 2.7.0, @('list') may cause an error when given too many
 arguments (generally, more than 63).  In such cases, @('list$') may be used in
 place of @('list'), since @('list$') has no restriction on the number of
 arguments.</p>")
other
(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)")
other
(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)")
other
(defxdoc lists
  :parents (programming)
  :short "Lists of objects, the classic Lisp data structure.")
other
(defxdoc live-stobj-in-proof
  :parents (raw-lisp-error)
  :short "Error messages about &ldquo;live&rdquo; @(see stobj)s during proofs"
  :long "<p>It is possible to see an error like the following.  (This error is
 probably very rare, and perhaps can only occur during a proof.)</p>

 @({
 ***********************************************
 ************ ABORTING from raw Lisp ***********
 ********** (see :DOC raw-lisp-error) **********
 Error:  A live stobj (for stobj ST) was unexpectedly encountered
         when evaluating a call of the function, ST-INIT.
         See :DOC live-stobj-in-proof.
 ***********************************************
 })

 <p>The solution is generally to @(see disable) the @(see
 executable-counterpart) of the offending function.  It may well be that the
 only way to get an unexpected &ldquo;live&rdquo; @(see stobj) is by the use of
 @(tsee swap-stobjs), as suggested by the example shown below (essentially
 provided by Sol Swords) &mdash; which results in a different error message,
 shown below, than the one above.</p>

 <p>First introduce a pair of congruent @(see stobj)s.</p>

 @({
 (defstobj st (fld))
 (defstobj st1 (fld1) :congruent-to st)
 })

 <p>Now define a function that &ldquo;initializes&rdquo; the stobj @('st') by
 creating a new stobj @('st1') and swapping the two (see @(see
 swap-stobjs)).</p>

 @({
 (defun st-init (st)
   (declare (xargs :stobjs (st)))
   (with-local-stobj st1
     (mv-let (st1 st)
       (swap-stobjs st1 st)
       st)))
 })

 <p>Here is a proof attempt that results in a raw Lisp error due to a live
 stobj being introduced by @(tsee swap-stobjs).</p>

 @({
 ACL2 !>(thm (not (equal (st-init '(1)) '(nil))))

 ***********************************************
 Note:  SWAP-STOBJS has been called on stobjs named ST1 and ST,
 where the value of ST1 is a live stobj but the value of ST is not.
 This is an error, as such calls are unsupported; see :DOC swap-stobjs.
 Advanced users may find it helpful to evaluate the form
 (set-debugger-enable :bt)
 to see a backtrace of calls leading to this error;
 see :DOC set-debugger-enable.
   Will attempt to exit the proof in progress;
   otherwise, the next interrupt will abort the proof.
   For an immediate abort see :DOC abort-soft.
 ***********************************************

 The message above might explain the error.  If not, and
 if you didn't cause an explicit interrupt (Control-C),
 then it may help to see :DOC raw-lisp-error.

 To enable breaks into the debugger (also see :DOC acl2-customization):
 (SET-DEBUGGER-ENABLE T)

 Summary
 Form:  ( THM ...)
 Rules: NIL
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)

 *** Note: No checkpoints to print. ***

 ACL2 Error [Failure] in ( THM ...):  See :DOC failure.

 ******** FAILED ********
 ACL2 !>
 })

 <p>In fact, that formula is not a theorem!  Through Version  8.6, ACL2
 mistakenly proved this alleged theorem by evaluating the indicated call of
 @('st-init') to obtain an actual Lisp array, because of how ACL2 handles @(see
 stobj)s in Lisp.  But now ACL2 produces the error displayed just above.</p>

 <p>The error is avoided if we @(see disable) the @(see executable-counterpart)
 of the offending function, @('st-init').  Indeed, the following theorem, which
 contradicts the false claim above and disables the offending
 executable-counterpart, shows that the logical value of @('(st-init '(1))') is
 indeed @(''(nil)').</p>

 @({
 (thm (equal (st-init '(1)) '(nil))
      :hints(("Goal" :in-theory (disable (:e st-init)))))
 })")
other
(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>")
other
(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).  (But see the Remark at the end of this topic about a related issue
 with guard-checking.)</p>

 <p>@(tsee Local) incompatibilities may be detected while trying to execute the
 strictly non-@(see local) @(see events) of an @(tsee encapsulate) or @(tsee
 certify-book) call.  For example, @('encapsulate') operates by first executing
 all the @(see events) (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 @(''include-book').
 @('Certify-book') does something similar, so that when @(tsee include-book)
 assumes the non-local events in the book, we are confident that the previously
 successful certification has performed the necessary 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 @(''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.  Similar analysis holds if the events in the @('encapsulate')
 call above are instead in a book.</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
 inclusion of a fully certified book.  Certification ensures against it.
 Therefore, if @(tsee include-book) reports an incompatibility, we claim 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 the ACL2
 implementors.</p>

 <p>When a @(tsee local) incompatibility is detected during the second pass of
 an @(tsee encapsulate) or @(tsee certify-book), the logical @(see world) is
 restored to what it was immediately before that call was evaluated.</p>

 <p>Note that for @('certify-book'), local incompatibility could be caused by
 an event that is local either in the certification world (see @(see
 portcullis)) or in the book itself.  ACL2 checks during @('certify-book') for
 local incompatibility by rolling back the world &mdash; back through the first
 portcullis command that generates a local event, or if there is none, then
 back through the first local event in the book (with the general exception of
 those inside an @('encapsulate'), but see final Remark below) &mdash; and then
 including the book.  But all that is skipped in the absence of either kind of
 local event.</p>

 <p>See @(see fast-cert) for a way to skip the local incompatibility check,
 although that may compromise soundness.</p>

 <p>Here is 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)))))
 })

 <p><b>Remark</b>.  We conclude by remarking that for ``local incompatibility''
 in the case of @('certify-book'), the notion of ``local'' is a bit more
 comprehensive than the name suggests, in that it can involve @(see
 guard)-checking in the following situation.  For example, in a fresh ACL2
 session evaluate the @(see command) @('(set-guard-checking :none)') followed
 by @('(table foo 0 (car 3))').  Then any attempt to certify a book should
 fail, since subsequent inclusion of that book would fail with a @(see guard)
 violation; that's because the @('set-guard-checking') call was not saved in
 the @(see certificate) file, hence was not evaluated when evaluating @('(car
 3)') while attempting to include the book.</p>

 <p>The example above may be helpful while reading the following general
 explanation of how local incompatibility incorporates the setting of
 guard-checking.  Suppose you are evaluating @(see command)s directly in the
 top-level read-eval-print loop.  One of those commands might be a call of
 @(tsee set-guard-checking) that weakens guard-checking from its default
 behavior, i.e., @('(set-guard-checking VAL)') where @('VAL') is other than
 @('t'), @(':nowarn'), or @(':all').  This command does not change the logical
 @(see world), so it will not be part of the book's @(see portcullis) commands.
 In that sense, it is like a @(see local) portcullis command.  ACL2 notices
 this case and insists that any portcullis event evaluated with guard-checking
 that is weaker than the default must be rolled back during the check for local
 incompatibilities.</p>")
other
(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
 @('(the integer 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)")
other
(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)")
other
(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)")
other
(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)")
other
(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)")
other
(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
 @('(the integer 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)")
other
(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 @(see 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>")
other
(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.  See @(tsee defun-mode-lambdas) for some
 clarifications of how @(':program') mode functions are allowed in certain
 @(':logic') mode terms.</p>

 @(def logic-fns-list-listp)")
other
(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.
 See @(tsee defun-mode-lambdas) for some clarifications of how @(':program')
 mode functions are allowed in certain @(':logic') mode terms.</p>

 @(def logic-fns-listp)")
other
(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.  See @(tsee defun-mode-lambdas) for some
 clarifications of how @(':program') mode functions are allowed in certain
 @(':logic') mode terms.</p>

 @(def logic-fnsp)")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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 ensure 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>")
other
(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>")
other
(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
 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>")
other
(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 <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>")
other
(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>")
other
(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>")
other
(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>target</i> term being
 an <see topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-INSTANCE)'>instance</see> of a
 <i>pattern</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 some target term, <i>target</i> that occurs in your goal conjecture
 is an instance of <i>pattern</i>.  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 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>")
other
(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>")
other
(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)")
other
(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)")
other
(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)")
other
(defxdoc logical-name
  :parents (events world)
  :short "A name created by a logical event"
  :long "@({
  Examples:
  assoc
  caddr
  +
  "ACL2-USER"
  :here
 })

 <p>A logical name is either a name introduced by some event, such as @(tsee
 defun), @(tsee defthm), or @(tsee defpkg), 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 package name (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.  We
 permit the keyword symbol @(':here') to be used as a logical name denoting the
 most recently completed event.</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>")
other
(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
 @('(the integer 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)")
other
(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)")
other
(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)")
other
(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)")
other
(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)")
other
(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)")
other
(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)")
other
(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
 @('(the integer 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)")
other
(defxdoc loop$
  :parents (acl2-built-ins programming)
  :short "Iteration with an analogue of the Common Lisp @('loop') macro"
  :long "<p>@('Loop$') is the ACL2 analogue of the Common Lisp's iteration
 primitive, @('loop').  This topic introduces the two classes of ACL2
 @('loop$') expressions, @('FOR') @('loop$')s and @('DO') @('loop$')s; see
 @(see for-loop$) and @(see do-loop$) (respectively) for their full
 documentation.</p>

 <p>@('Loop$') was introduced into ACL2 in Version 8.2 (May, 2019), over 20
 years after ACL2 was first released.  So there are many experienced ACL2 users
 who have never used @('loop$').  The @('Loop$') Primer, see @(see
 loop$-primer), is textbook-style introduction, meant to be read linearly and
 may be a good starting place for you.  The primer follows a &ldquo;monkey-see
 monkey-do&rdquo; approach, showing lots of examples.  Sample proofs are worked
 out in detail and then the reader is challenged to apply those lessons to
 exercises.  Solutions to the exercises are provided in books among the
 Community Books.  Depending on your preferred learning style and familiarity
 with @('loop$') and ACL2 in general, you might want to work your way through
 the primer (see @(see loop$-primer)) instead of bouncing around the hypertext
 user's manual.</p>

 <p>The Introduction below is followed by a discussion of types and guards.
 For a discussion of how to state effective lemmas about @('loop$')s and how to
 prove inductive theorems about @('loop$')s see @(see
 stating-and-proving-lemmas-about-loop$s).  Also, for a summary of how the
 rewriter handles @('apply$'), @('ev$'), and @('loop$') @(see scion)s, see
 @(see rewriting-calls-of-apply$-ev$-and-loop$-scions).</p>

 <p>But before we get started we emphasize a few key points.</p>

 <ul>

 <li>As noted, The Loop$ Primer (see @(see loop$-primer)) may be a good place
 to start if you're using ACL2 @('loop$')s for the first time.</li>

 <li>The Table of Contents of the Loop$ Primer (see @(see lp-section-0)) lists
 some sensible entry points to the primer.  You'll see sections devoted to
 examples, sample proofs, exercises, etc.  Keep the primer in mind as an
 additional resource.  For example, you might visit @('Loop$') Primer Section
 6 (@(see lp-section-6)) for some exercises on writing @('loop$')s and, when
 you get to the end, ignore the &ldquo;Now go to @(see lp-section-7),&rdquo;
 and use your browser's Back key to return to the general hypertext user's
 manual.</li>

 <li><b>Many examples</b> of @(tsee loop$) expressions may be found in @(see
 community-book) @('projects/apply/loop-tests.lisp').</li>

 <li>The semantics of @('loop$') involve @('apply$').  Therefore, before using
 @('loop$'), it is <b>strongly recommended</b> that you include the same book
 as is typically included when using @(tsee apply$), as follows.

 @({
 (include-book "projects/apply/top" :dir :system)
 })</li>

 <li>ACL2 @('loop$') statements are executed as Common Lisp @('loop')
 statements after the relevant @(see guard) conjectures are proved.  Common
 Lisp @('loop') statements generally execute much faster than
 equivalent (tail-recursive) functions.</li>

 <li><b>Warning:</b> @('Loop$') implements only a modest part of the
 functionality of Common Lisp's @('loop').  Aside from the simple fact that
 @('loop$') allows only a limited subset of the syntax of @('loop'), the main
 restriction is that the subexpressions of the @('loop$') expression that are
 evaluated repeatedly must be @(see tame)!  These expressions include not only
 the loop body but, if present, the @('UNTIL') test, the @('WHEN') test, and
 the @('FINALLY') clause (all discussed below).  Thus, all the function
 symbols used in these expressions must be @(see badge)d (see @(tsee defbadge)
 and @(tsee defwarrant)).  Further restrictions are enforced for @(tsee
 defun)'d functions in which recursive calls appear in @('loop$') bodies, but
 we say little about that in this documentation topic; see @(see
 loop$-recursion).  We recommend that users unfamiliar with @('loop$')
 acquaint themselves with the material below and in @(see for-loop$) before
 wading into @('loop$-recursion')!</li>

 </ul>

 <h3>Introduction to @('loop$')</h3>

 <p>As noted above, there are two classes of @('loop$') expressions.  These are
 identified as follows.</p>

 <ul>

 <li>@('FOR') loop$ expressions:

 @({
 (loop$ FOR ...)
 })

 </li>

 <li>@('DO') loop$ expressions:

 @({
 (loop$ WITH ... DO ...)
 })

 </li>

 </ul>

 <p>Below we introduce these two classes of @('loop$') expressions.  For full
 documentation see the topic for each class: see @(see for-loop$) for @('FOR')
 @('loop$')s and @(see do-loop$) for @('DO') @('loop$')s.  In particular
 various restrictions are discussed in those topics, but for now we mention
 just the following.  While @('FOR') @('loop$') expressions are often more
 convenient to use than @('DO') @('loop$') expressions, their @('UNTIL'),
 @('WHEN'), and body expressions are not permitted to reference @(tsee state)
 or @(see stobj)s, and they always return a single value.  @('DO') @('loop$')
 expressions do not have these restrictions, but they may not use the idioms of
 @('FOR') @('loop$')s, like ``@('FOR x IN ...')'' or ``@('UNTIL p')''.</p>

 <p>ACL2's @('loop$') is considerably more restrictive than Common Lisp's
 @('loop'), but when an ACL2 @('loop$') expression is translated without error
 it has the same meaning as the corresponding Common Lisp @('loop').
 @('Loop$') supports @(':')@(tsee GUARD) expressions (discussed below) in
 certain places and these are ignored by Common Lisp.</p>

 <p>Next we present some @('FOR') @('loop$') examples.  They illustrate the
 three supported forms of @('FOR') @('loop$') iteration: the use of @('IN'), to
 iterate over elements of a list; the use of @('ON'), to iterate over the
 non-empty tails of a list; and the use of @('FROM .. TO'), to iterate over a
 range of integers (optionally with @('BY') to specify the increment at each
 step).  These examples also illustrate the use of @('WHEN') to restrict which
 iterations are considered and the use of @('UNTIL') to terminate early.
 Additional keywords illustrated are @('OF-TYPE') to specify types and @('AS')
 to specify additional iteration variables.  They also illustrate some of the
 operations permitted at each iteration, such as @('SUM') and @('COLLECT').</p>

 @({
 ACL2 !>(loop$ for x in '(1 2 3) sum (* x x))
 14
 ACL2 !>(loop$ for x in '(1 2 3) collect (* x x))
 (1 4 9)
 ACL2 !>(loop$ for x on '(1 2 3) collect x)
 ((1 2 3) (2 3) (3))
 ACL2 !>(loop$ for x of-type integer from -10 to 10 by 2 collect x)
 (-10 -8 -6 -4 -2 0 2 4 6 8 10)
 ACL2 !>(loop$ for i from 1 to 10
               as  x in '(a b c d e f g)
               collect (cons i x))
 ((1 . A)
  (2 . B)
  (3 . C)
  (4 . D)
  (5 . E)
  (6 . F)
  (7 . G))
 ACL2 !>(loop$ for i from 1 to 10
               as  x in '(a b c d e f g)
               until (> i 6)
               collect (cons i x))
 ((1 . A)
  (2 . B)
  (3 . C)
  (4 . D)
  (5 . E)
  (6 . F))
 ACL2 !>(loop$ for i from 1 to 10
               as  x in '(a b c d e f g)
               until (> i 6)
               when (evenp i)
               collect (cons i x))
 ((2 . B) (4 . D) (6 . F))
 })

 <p>Finally we present two @('DO') @('loop$') examples.  We explore them
 further in the documentation specific to @('DO') @('loop$') expressions; see
 @(see do-loop$).</p>

 <p>Our first @('DO') @('loop$') example shows iteration with the indicated
 initial values for local variables @('x') and @('y').  They are modified at
 each iteration through the loop until @('x') is empty, at which point the
 value of @('y') is returned.  (See @(see do-loop$) for more thorough
 explanations.)</p>

 @({
 ACL2 !>(loop$ with x = '(a b c)
               with y = nil
               do (cond ((consp x)
                         (progn (setq y (cons (car x) y))
                                (setq x (cdr x))))
                        (t (return y))))
 (C B A)
 ACL2 !>
 })

 <p>Our second example of a @('DO') @('loop$') expression illustrates more
 features than the first.  Also, it illustrates the use of a @('loop$')
 expression inside a definition, which is allowed for both @('FOR') @('loop$')s
 and @('DO') @('loop$')s.  We see here that @(see stobj)s and @(see
 multiple-value) returns are allowed for @('DO') @('loop$')s, where the
 @(':VALUES') keyword specifies the shape of the return.  We also see here the
 use of the optional @(':GUARD') keyword of a @('loop$') expression (legal for
 both classes of @('loop$')s, as discussed further below) and the optional
 @(':MEASURE') keyword of a @('DO') @('loop$') expression.</p>

 <p>But notice the @(tsee defwarrant) events below!  They are required because
 the functions @('fld') and @('update-fld') are not system primitives.  They
 are introduced by the user's @(tsee defstobj) event below.  This is in
 contrast to the @('DO') @('loop$') in our first example above where no
 warrants are required because all the functions in that example are
 primitive.</p>

 <p>The semantics of @('loop$') involve @('apply$') and thus @('loop$')s
 inherit the restrictions imposed on @('apply$') and its @(see scion)s.  Among
 those restrictions are that (a) unwarranted @(':logic') mode functions cannot
 be @('apply$')'d in the top-level read-eval-print loop and (b) proofs about
 the applications of unwarranted functions are impossible.  Restriction (a)
 means you cannot even execute a @(':logic') mode @('loop$') containing
 unwarranted functions.  Restriction (b) means you can't verify the @(see
 guard)s of such @('loop$').  This last point obviates the main reason for
 using @('loop$'): its fast execution as a Common Lisp loop once guards are
 verified.</p>

 <p>Now here is our second example.</p>

 @({

 (defstobj st fld)
 (include-book "projects/apply/top" :dir :system) ; needed for defwarrant
 (defwarrant fld)
 (defwarrant update-fld)

 (defun test-loop$ (i0 max st)
   (declare (xargs :guard (and (natp i0) (natp max))
                   :stobjs st))
   (loop$ with i of-type (satisfies natp) = i0
          with cnt of-type integer = 0
          do
          :measure (nfix (- max i))
          :guard (and (natp max)
                      (natp cnt)
                      (stp st))
          :values (nil st) ; shape of return; can be omitted when it's (nil)
          (if (>= i max)
              (loop-finish)
            (progn (setq st (update-fld i st))
                   (mv-setq (cnt i)
                            (mv (+ 1 cnt) (+ 1 i)))))
          finally
          :guard (stp st)
          (return
           (mv (list 'from i0 'to max 'is cnt 'steps 'and 'fld '= (fld st))
               st))))

 ACL2 !>(test-loop$ 3 8 st)
 ((FROM 3 TO 8 IS 5 STEPS AND FLD = 7)
  <st>)
 ACL2 !>
 })

 <p>Both classes of @('loop$') expressions (@('FOR') and @('DO') @('loop$')s)
 rely heavily on the ACL2 built-in function, @(tsee apply$): in each iteration
 through the loop, a @(see lambda) object based on the body of the @('loop$')
 is given as the function argument of @('apply$').  Similarly, the @('UNTIL')
 and @('WHEN') clauses of @('FOR') @('loop$')s and the @(':measure') and
 @('FINALLY') clauses of @('DO') @('loop$')s are translated into @('lambda')
 objects.  The functions in all those @('lambda') objects must be warranted to
 evaluate the @('loop$') and/or prove its properties (including its guards)
 because logically the application of an unwarranted function is
 undefined.  (However, recall from @(see guarantees-of-the-top-level-loop) that
 @(':program') mode functions do not need warrants, just badges, for execution
 in the evaluation theory.)</p>

 <p>The documentation for @(tsee apply$) illustrates a simple @('defun') that
 is inadmissible because the measure theorem cannot be proved without a warrant
 and warrants cannot be assumed during the proofs of the measure conjectures.
 The same issue arises when one of the functions critically involved in a
 measure conjecture is defined using a @('loop$') whose body involves a
 user-defined function.  For a simple example of this issue and how to work
 around it, see @(see community-book)
 @('books/demos/measure-and-warrant.lisp').</p>

 <h3>Types and guards in @('loop$') expressions</h3>

 <p>In this section we document basic aspects of the @('OF-TYPE') and
 @(':GUARD') keywords in @(tsee loop$) expressions.  See @(see for-loop$) and
 @(see do-loop$) for detailed documentation on guards for @('FOR') and @('DO')
 @('loop$') expressions, respectively.</p>

 <p>@('Loop$') expressions execute fastest when they are @(see guard)
 verified.  But the @('loop$') body raises interesting guard verification
 problems, as do the @('UNTIL') and @('WHEN') tests of a @('FOR') @('loop$'),
 because they are executed for many different values of the iteration
 variables.  The @('FINALLY') clause of a @('DO') @('loop$') raises a similar
 concern, since the values of its variables may be modified repeatedly by
 execution of the @('loop$') body.  It may be necessary to provide type
 information or even stronger invariants to verify guards for @('loop$')s.  We
 now provide a few examples illustrating the handling of guards in
 @('loop$').</p>

 <p>The first example below is an acceptable @('loop$') expression but cannot
 be guard verified, as would be necessary if it appeared in a @(tsee defun)
 that was to be guard verified.  The problem is that @('(+ 1 x)') requires
 @('x') to be numeric and, in general, we don't know anything about the value
 of @('x') here.  (Actually, because the target range is just a constant below,
 ACL2 could deduce information about each value @('x') takes on, but it
 doesn't.)  The second example can be guard verified and has the advantage of
 being standard Common Lisp, so compilers might optimize the handing of @('(+ 1
 x)').  The third example can also be guard verified but since the @(':GUARD')
 directive used here is ignored by Common Lisp it does not inform the compiler,
 so this example might execute more slowly than the previous one.  The last
 example shows the syntax and use of the ACL2-specific addition to @('loop$'):
 the @(':GUARD') directive protecting, in this case, the @('loop$') body.
 @(':GUARD') is useful when you wish to add more guard information than can be
 expressed with the Common Lisp @('OF-TYPE') directive.  The @('OF-TYPE') and
 @(':GUARD') directives are conjoined to form the actual guard protecting the
 @('loop$') body.</p>

 @({
 ACL2 !>(loop$ for x in '(1 2 3) collect (+ 1 x))
 (2 3 4)
 ACL2 !>(loop$ for x of-type integer in '(1 2 3) collect (+ 1 x))
 (2 3 4)
 ACL2 !>(loop$ for x in '(1 2 3) collect :guard (integerp x) (+ 1 x))
 (2 3 4)
 ACL2 !>(let ((max 10))
         (loop$ for x of-type integer in '(1 2 3)
                collect
                :guard (and (integerp max) (< x max))
                (- max x)))
 (9 8 7)
 })

 <p>The guard on the @('(- max x)') above is @('(and (integerp x) (integerp
 max) (< x max))') and the compiler is informed that @('x') is an integer by
 the @('OF-TYPE').</p>

 <p>The examples just above are of @('FOR') @('loop$')s.  Here is a @('DO')
 @('loop$') example that illustrates types and guards.</p>

 @({
 ACL2 !>(loop$ with i of-type integer = 7
               with ans = nil
               do
               :guard (true-listp ans)
               (progn (setq ans (cons i ans))
                      (setq i (- i 2))
                      (if (< i 0) (loop-finish) t))
               finally
               :guard (true-listp ans)
               (return (reverse ans)))
 (7 5 3 1)
 ACL2 !>
 })

 <p>Neither @(':GUARD') is necessary in order for this execution to complete.
 However, if this @('loop$') is put into a definition &mdash; @('(defun foo ()
 (loop$ ...))') &mdash; then both @(':GUARD') expressions are necessary in
 order for the definition to be @(see guard)-verified.</p>

 <p>As suggested above, when a @('loop$') expression occurs in the body of a
 @(see guard)-verified function, it will be executed as a Common Lisp
 @('loop') expression, which can be much more efficient than executing without
 such guard verification.  This efficiency can also be gained in top-level
 @('loop$') expressions if the @(see tau-system) completes (silently) the
 necessary guard verification.  See @(see print-cl-cache).</p>")
other
(defxdoc loop$-primer
  :parents (loop$ documentation programming)
  :short "Primer for using @(tsee loop$)"
  :long "<h1>The Loop$ Primer</h1>

  <h3>Preface</h3>

  <p>This primer was created at the request of and with the support of
  Warren Hunt.  It was originally conceived as a standalone document,
  but it has been integrated into the ACL2 documentation to increase
  its utility.</p>

  <p>The ACL2 @(tsee loop$) feature is an iteration primitive modeled on a
  small subset of the Common Lisp @('loop') facility.  This documentation is
  an elementary introduction to @('loop$') for use in both programming and proofs.  We
  assume the reader is already an experienced ACL2 user who is just new to
  @('loop$').</p>

  <p>@('Loop$') exploits ACL2's &ldquo;higher order&rdquo; capability using @(tsee
  apply$).  Logically, @('loop$') expressions are translated into calls of
  @(see scion)s or &ldquo;mapping functions&rdquo; that map one or more @(tsee
  lambda) objects over ranges.  When @('loop$') expressions are typed into the
  ACL2 top-level loop these formal semantics are executed, which can be
  inefficient.  When @('loop$') expressions are in @(see guard) verified (see @(tsee
  verify-guards)) functions they are compiled into Common Lisp @('loop')
  expressions and are executed very efficiently.</p>

  <p>Two issues complicate the situation.  First, Common Lisp's @('loop')
  facility is extraordinarily complex, requiring a full chapter of the reference
  manual to explain.  See <a
  href='http://www.lispworks.com/documentation/HyperSpec/Body/m_loop.htm#loop'>loop</a>
  in the Common Lisp HyperSpec or Chapter 26 (pages 709-747) of Guy Steele's
  monumental <b>Common Lisp The Language, Second Edition</b>.  Second, ACL2's
  logic is first-order, not higher-order, and so the @('apply$')-based
  semantics imposes restrictions that new users of ACL2 may find hard to deal
  with.</p>

  <p>This primer focuses on how to write @('loop$') expressions and how to prove things
  about them.  We start by asking you some questions that test your basic
  knowledge of ACL2, so that you can decide whether this primer is right for
  you.  Then we discuss the so-called &ldquo;@('FOR')&rdquo; @('loop$') and
  later move on to the &ldquo;@('DO')&rdquo; @('loop$').  We follow the
  &ldquo;monkey see, monkey do&rdquo; teaching style.  We informally and
  incompletely sketch the syntax and semantics, but we provide lots of examples
  and we offer many challenge problems for you to solve.  Answers are also
  provided.</p>

  <p>There are two glaring omissions in this primer: @(see guard) verification and the
  use of @(see stobj)s in @('DO') @('loop$').</p>

  <p>While guard verification is crucial to the efficient execution of
  @('loop$')s by Common Lisp, we omitted much discussion of it because guard
  obligations are generated automatically and are generally just
  &ldquo;ordinary&rdquo; conjectures that we assume the experienced user can
  figure out how to prove.  The newcomer to @('loop$') may wonder &ldquo;why am
  I having to prove this?&rdquo; but the answer is always the same: &ldquo;the
  Common Lisp compiler requires this in order for @('loop$') to behave like
  @('loop').&rdquo;  Often the &ldquo;fix&rdquo; to a @('loop$') guard
  verification problem is to add a @(':guard') to the @('loop$') body,
  remembering that it is translated into a @('lambda') object that must be
  guard verified in isolation since it might be passed around and applied in
  many contexts.  We include the syntax for @('loop$') guards.</p>

  <p>We omitted much discussion of stobjs &mdash; which are allowed in @('DO')
  @('loop$')s but not in other kinds of @('loop$')s &mdash; because they raise
  the same problems in @('DO') @('loop$')s as they do in &ldquo;ordinary&rdquo;
  uses: syntactic single-threadedness into, through, and out of expressions.
  We assume the experienced user knows how to deal with these issues.</p>

  <p>There is a strong emphasis in this primer on problems for you to work on.
  The best way to learn how to do something is to practice doing it!</p>

  <p>The primer is divided into subjects listed in the Table of Contents which
  is at the link @(see lp-section-0).  We recommend you read these sections in
  the order shown.  Each section ends with a pointer to the next section but
  also includes a link to the Table of Contents.</p>

  <p>Now go to @(see lp-section-1).  The Table of Contents is at @(see
  lp-section-0).</p>")
other
(order-subtopics loop$-primer
  (lp-section-0 lp-section-1
    lp-section-2
    lp-section-3
    lp-section-4
    lp-section-5
    lp-section-6
    lp-section-7
    lp-section-8
    lp-section-9
    lp-section-10
    lp-section-11
    lp-section-12
    lp-section-13
    lp-section-14
    lp-section-15
    lp-section-16
    lp-section-17
    lp-section-18))
other
(defxdoc lp-section-0
  :parents (loop$-primer)
  :short "Loop$ Primer Table of Contents)"
  :long "<h3>The Loop$ Primer Table of Contents</h3>

  <ul>
  <li>@(see loop$-primer):&nbsp;&nbsp; Preface<br/></li>
  <li>lp-section-0:&nbsp;&nbsp; Table of Contents<br/></li>
  <li>@(see lp-section-1):&nbsp;&nbsp; Background Reviews<br/></li>
  <li>@(see lp-section-2):&nbsp;&nbsp; @('Loop') in Common Lisp and @('loop$') in ACL2<br/></li>
  <li>@(see lp-section-3):&nbsp;&nbsp; Examples of @('FOR') @('Loop$')s<br/></li>
  <li>@(see lp-section-4):&nbsp;&nbsp; Syntax of @('FOR') @('Loop$')s<br/></li>
  <li>@(see lp-section-5):&nbsp;&nbsp; Informal Semantics of @('FOR') @('Loop$')s<br/></li>
  <li>@(see lp-section-6):&nbsp;&nbsp; Challenge Problems about @('FOR') @('Loop$')s<br/></li>
  <li>@(see lp-section-7):&nbsp;&nbsp; Using @('Loop$')s and Guards in @('Defun')s<br/></li>
  <li>@(see lp-section-8):&nbsp;&nbsp; Challenge Problems about @('FOR') @('Loop$') in @('Defun')s<br/></li>
  <li>@(see lp-section-9):&nbsp;&nbsp; Semantics of @('FOR') @('Loop$')s<br/></li>
  <li>@(see lp-section-10): The Evaluation of the Formal Semantics of a Fancy @('Loop$')<br/></li>
  <li>@(see lp-section-11): Proving Theorems about @('FOR') @('Loop$')s<br/></li>
  <li>@(see lp-section-12): Challenge Proof Problems about @('FOR') @('Loop$')s<br/></li>
  <li>@(see lp-section-13): Examples of @('DO') @('Loop$')s<br/></li>
  <li>@(see lp-section-14): Challenge Problems about @('DO') @('Loop$')s<br/></li>
  <li>@(see lp-section-15): Informal Syntax and Semantics of @('DO') @('Loop$')s<br/></li>
  <li>@(see lp-section-16): Proving Theorems about @('DO') @('Loop$')s<br/></li>
  <li>@(see lp-section-17): Challenge Proof Problems for @('DO') @('Loop$')s<br/></li>
  <li>@(see lp-section-18): Conclusion<br/></li>
  <li>lp-section-0:&nbsp;&nbsp; Table of Contents<br/></li>
  </ul>
  ")
other
(defxdoc lp-section-1
  :parents (loop$-primer)
  :short "Background Reviews"
  :long "<h3>LP1: Background Reviews</h3>

  <p>We assume you're familiar with elementary Common Lisp and ACL2.  The
  questions and answers in @(see lp-background-review-1) offer a
  quick review.  Come back here when you're comfortable with such
  questions.</p>

  <p>@('Loop$') makes extensive use of ACL2's limited second order
  functionality.  The questions and answers in @(tsee
  lp-background-review-2) offer a quick review of the main features
  and limitations of @('apply$') and the related concepts.  We assume you're
  comfortable with these features too.</p>

  <p>Now go to @(see lp-section-2) (or return to the <see topic='@(url
  lp-section-0)'> Table of Contents</see>).</p>")
other
(defxdoc lp-section-2
  :parents (loop$-primer)
  :short "@('Loop') in Common Lisp and @('loop$') in ACL2"
  :long "<h3>LP2: @('Loop') in Common Lisp and @('loop$') in ACL2</h3>

  <p>The @('loop') macro of Common Lisp was inspired by the &ldquo;iterative
  statements&rdquo; in Warren Teitelman's CLISP package of Interlisp (1974).  But
  programming languages have had iterative statements since early in the
  development of compilers.  The first release of a FORTRAN compiler (1957)
  supported what is probably the most well-known iterative construct, the &ldquo;DO
  loop.&rdquo;  But CLISP added many additional features including simultaneous
  looping over multiple ranges, structured ways to filter the elements,
  structured exit control mechanisms, and multiple ways to accumulate the
  results.  Common Lisp supports these and many other features.</p>

  <p>ACL2's @('loop$') facility supports a tiny subset of Common Lisp's
  @('loop') statements.  It is hard to overstate how small the ACL2 subset is!
  For example, to manage iteration over a range of numbers, ACL2 provides
  @('FROM'), @('TO'), and @('BY'), but Common Lisp additionally provides
  @('DOWNFROM'),@('UPFROM'),@('DOWNTO'),@('UPTO'),@('BELOW'),and @('ABOVE').
  For value accumulation, ACL2 supports @('SUM'), @('COLLECT'), @('APPEND'),
  @('ALWAYS'), and @('THEREIS'), while Common Lisp also supports @('NCONC'),
  @('COUNT'), @('MAXIMIZE'), and @('MINIMIZE').  Even within its restricted
  subset, ACL2 syntax is less flexible regarding the order of the various
  &ldquo;clauses&rdquo; and the presence of, say, multiple accumulators.  The list of
  differences could go on and on because the Common Lisp facility is so
  elaborate.</p>

  <p>While many more Common Lisp @('loop') features could be supported in ACL2,
  we believe it is best to test and refine the techniques reasoning about
  @('loop$') before elaborating it further.</p>

  <p>Now go to @(see lp-section-3) (or return to the <see topic='@(url lp-section-0)'>
  Table of Contents</see>).</p>")
other
(defxdoc lp-section-3
  :parents (loop$-primer)
  :short "Examples of @('FOR') @('Loop$')s"
  :long "<h3>LP3: Examples of @('FOR') @('Loop$')s</h3>

  <p>Below is the complete log of an ACL2 session demonstrating the behavior of
  @('FOR') @('loop$')s.  ACL2 also supports @('DO') @('loop$')s but they are
  not illustrated here.  Note that to use @('loop$') one should always work in
  a session in which the book shown below is included.  The examples below do
  not illustrate guards, the use of user defined functions in @('loop$')
  expressions, or proofs about @('loop$')s.</p>

  <p>We'll describe the syntax and semantics of @('loop$') in the next two
  sections. But we expect you can intuit the syntax and semantics of @('loop$')
  statements from these examples alone.  Please try!</p>

  @({
  ACL2 !>(include-book "projects/apply/top" :dir :system)

  Summary
  Form:  ( INCLUDE-BOOK "projects/apply/top" ...)
  Rules: NIL
  Time:  1.00 seconds (prove: 0.00, print: 0.00, other: 1.00)
   "/Users/demo/books/projects/apply/top.lisp"

  ACL2 !>(loop$ for x in '(a b c)
                collect (cons 'hi x))
  ((HI . A) (HI . B) (HI . C))

  ACL2 !>(loop$ for x in '(a b c)
                when (not (eq x 'b))
                collect (cons 'hi x))
  ((HI . A) (HI . C))

  ACL2 !>(loop$ for x in '(a b c d e f g)
                until (eq x 'd)
                collect x)
  (A B C)

  ACL2 !>(loop$ for x on '(a b c)
                collect x)
  ((A B C) (B C) (C))

  ACL2 !>(loop$ for x on '(a b c)
                collect (cons (car x) (len x)))
  ((A . 3) (B . 2) (C . 1))

  ACL2 !>(loop$ for i from 1 to 10 sum i)
  55

  ACL2 !>(loop$ for i from 1 to 12 by 3
                collect (* i i))
  (1 16 49 100)

  ACL2 !>(loop$ for x in '((a b c) (d e f) (g h i))
                collect (cons 'hi x))
  ((HI A B C) (HI D E F) (HI G H I))

  ACL2 !>(loop$ for x in '((a b c) (d e f) (g h i))
                append (cons 'hi x))
  (HI A B C HI D E F HI G H I)

  ACL2 !>(loop$ for x in '(2 4 6)
                always (evenp x))
  T

  ACL2 !>(loop$ for x in '(2 4 5 6)
                always (evenp x))
  NIL

  ACL2 !>(loop$ for x in '(2 4 5 6)
                thereis (if (evenp x) nil x))
  5

  ACL2 !>(let ((greeting 'hi))
           (loop$ for x in '(a b c)
                  collect (cons greeting x)))
  ((HI . A) (HI . B) (HI . C))

  ACL2 !>(loop$ for x in '(a b c)
                as  y in '(65 66 67 68)
                collect (cons x y))
  ((A . 65) (B . 66) (C . 67))

  ACL2 !>(loop$ for x in '(a b c d)
                as  y in '(65 66 67)
                collect (cons x y))
  ((A . 65) (B . 66) (C . 67))

  ACL2 !>(loop$ for x in '((1 2 3) (4 5 6) (7 8 9))
                collect
                (loop$ for i in x collect (* i i)))
  ((1 4 9) (16 25 36) (49 64 81))
  })

  <p>Now go to @(see lp-section-4) (or return to the <see topic='@(url
  lp-section-0)'>Table of Contents</see>).</p>")
other
(defxdoc lp-section-4
  :parents (loop$-primer)
  :short "Syntax of @('FOR') @('Loop$')s"
  :long "<h3>LP4: Syntax of @('FOR') @('Loop$')s</h3>

  <p>To describe the syntax of @('FOR') @('loop$')s we first describe the most
  elaborate @('FOR') @('loop$').  Then we note which elements can be omitted.
  The most elaborate @('FOR') @('loop$') is of the form</p>

  <p>&nbsp; &nbsp; &nbsp; &nbsp; @('(LOOP$ FOR ')<i>v1</i>@(' OF-TYPE ')<i>spec1
  target1</i><br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
  &nbsp; &nbsp; &nbsp; &nbsp; @('AS ') &nbsp; <i>v2</i>@(' OF-TYPE ')<i>spec2
  target2</i><br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
  &nbsp; &nbsp; &nbsp; &nbsp; ...<br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
  &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @('AS ') &nbsp; <i>vn</i>@('
  OF-TYPE ')<i>specn targetn</i><br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
  &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @('UNTIL :GUARD ')<i>guard1
  until-expr</i><br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
  &nbsp; &nbsp; &nbsp; &nbsp; @('WHEN ') &nbsp; @(':GUARD ')<i>guard2
  when-expr</i><br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
  &nbsp; &nbsp; &nbsp; <i>op</i>@(' :GUARD ')<i>guard3
  body-expr</i>@(')')<br/></p>

  <p>where</p>

  <ul>

  <li>each <i>vi</i> &nbsp; is a legal variable symbol, they are all distinct,
  and are collectively called the <i>iteration variables</i>,</li>

  <li>each <i>speci</i> &nbsp; is a @(tsee type-spec) for the corresponding
  variable <i>vi</i>,</li>

  <li>each <i>targeti</i> is of one of the forms below and specifies the range
  of values to be taken by the corresponding variable <i>vi</i>.  Abstractly
  you may think of the &ldquo;range&rdquo; here simply as a list of the values as
  described below, where <i>list-expr</i> is a term (which is expected to
  evaluate to a true list), <i>lo-expr</i> and <i>hi-expr</i> are terms (which
  are expected to evaluate to integers), and <i>step-expr</i> is a term (which
  is expected to evaluate to a positive integer).  In the examples given below,
  let @('rv') be the list reverse function, so @('(rv '(a b c))') is @('(C B A)').

  <ul>

  <li>@('IN') <i>list-expr</i> &mdash; range is the value of <i>list-expr</i>.
  For example, the range of &ldquo;@('IN') @('(rv '(a b c))')&rdquo; is @('(C B
  A)').</li>

  <li>@('ON') <i>list-expr</i> &mdash; range is the list of successive
  non-@('nil') tails of the value of <i>list-expr</i>.  For example, the range
  of &ldquo;@('ON') @('(rv '(a b c))')&rdquo; is @('((C B A) (B A) (A))').  The range
  value is produced by @('(TAILS ')<i>list-expr</i>@(')').</li>

  <li>@('FROM') <i>lo-expr</i> @('TO') <i>hi-expr</i> @('BY') <i>step-expr</i>
  &mdash; If &ldquo;@('BY') <i>step-expr</i>&rdquo; is omitted, &ldquo;@('BY 1')&rdquo; is used.
  The range contains all the integers from the value of <i>lo-expr</i> to the
  greatest integer less than or equal to the value of <i>hi-expr</i> such that
  each is separated from its higher neighbor by the value of <i>step-expr</i>.
  For example, the range of &ldquo;@('FROM') 1 @('TO') 10 @('BY') 2&rdquo; is @('(1 3 5 7
  9)').  The range value is produced by @('(FROM-TO-BY ')<i>lo-expr</i>
  <i>hi-expr</i> <i>step-expr</i>@(')').</li>

  </ul>
  </li>

  <li>each <i>guardi</i> is a term,</li>

  <li>each <i>until-expr</i>, <i>when-expr</i>, and <i>body-expr</i>
  &nbsp; is a @(tsee tame) term, and</li>

  <li><i>op</i> &nbsp; is one of the <i>operators</i> &nbsp;
  @('SUM'), @('COLLECT'), @('APPEND'), @('ALWAYS'), or @('THEREIS').</li>

  </ul>

  <p>The symbols @('FOR'), @('IN'), @('ON'), @('FROM'), @('TO'), @('BY'),
  @('OF-TYPE'), @('WHEN'), @('UNTIL'), @('SUM'), @('COLLECT'), @('APPEND'),
  @('ALWAYS'), and @('THEREIS') when used in @('loop$') statements may be in
  any package.</p>

  <p>Common Lisp prohibits loops with both a @('WHEN') clause and either an
  @('ALWAYS') or a @('THEREIS') operator.  For example, if you are tempted to
  write &ldquo;@('WHEN') <i>p</i> @('ALWAYS') <i>q</i>&rdquo; you can instead write
  &ldquo;@('ALWAYS') @('(if ')<i>p q</i> @('t)').&rdquo;</p>

  <p>The following elements may be omitted from the most elaborate form and
  still produce legal @('loop$') statements:</p>

  <ul>
  <li>any line beginning with @('AS'), @('UNTIL') or @('WHEN'),</li>

  <li>any @('OF-TYPE') <i>speci</i>, and</li>

  <li>any @(':GUARD') <i>guardi</i>.</li>

  </ul>

  <p>A @('FOR') @('loop$') expression with just one iteration variable and in
  which the iterative expressions mention no free variable other than the
  iteration variable is called a <i>simple @('loop$')</i> (or, sometimes, a
  <i>simple loop</i>).  An example of a simple loop is</p>

  @({
  (loop$ for x in lst when (evenp x) collect (+ 1 (sq x))).
  })

  <p>A @('FOR') @('loop$') expression is called a <i>fancy @('loop$')</i> if it
  is not simple.  Both of the following @('loop$')s are fancy.</p>

  @({
  (loop$ for x in xlst as y on ylst collect (expr x y))

  (loop$ for x in xlst collect (expr x z))
  })

  <p>The first is fancy because it has two iteration variables, @('x') and
  @('y').  The second is fancy because the body freely uses the variable @('z')
  which is not the iteration variable.</p>

  <p>Now go to @(see lp-section-5) (or return to the <see topic='@(url
  lp-section-0)'>Table of Contents</see>).</p>")
other
(defxdoc lp-section-5
  :parents (loop$-primer)
  :short "Informal Semantics of @('FOR') @('Loop$')s"
  :long "<h3>LP5: Informal Semantics of @('FOR') @('Loop$')s</h3>

  <p>The value returned by a @('FOR') @('loop$') can be specified as follows
  &mdash; but we hasten to add that this is not how Common Lisp compilers
  implement @('loop$')!  We think this description is easier to understand.</p>

  <p>The first step in evaluating a @('FOR') @('loop$') is to determine the
  range of each iteration variable by evaluating the target expressions as
  previously described.</p>

  <p>Next, repeat the following steps until the process stops.
  (1) If any range is empty, stop.  (2) Otherwise, assign each iteration
  variable the first value in its range and shorten the range by one, by
  removing that first element.  (3) If the <i>until-expr</i> evaluates to
  non-@('nil') under the current values of the global and iteration variables,
  stop.  Otherwise, if the <i>when-expr</i> evaluates to non-@('nil') under the
  current values of the variables, then evaluate the <i>body-expr</i> under the
  current values.  Otherwise, do not evaluate the <i>body-expr</i>.</p>

  <p>When the repetition stops, the <i>body-expr</i> will have been evaluated
  <i>n</i> times, each time producing a value <i>vali</i>, 0 &lt;= <i>i</i> &lt;
  <i>n</i>, where the <i>vali</i> are listed in the order in which they were
  produced.  The result returned by the @('loop$') is determined by the
  operator, <i>op</i>, of the @('loop$') as follows.</p>

  <ul>
  <li>@('SUM') &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&mdash; return the sum of the <i>vali</i></li>
  <li>@('COLLECT') &mdash; return @('(LIST ')<i>val1</i> ... <i>valn</i>@(')')</li>
  <li>@('APPEND') &nbsp; &mdash; return @('(APPEND ')<i>val1</i> ... <i>valn</i>@(')')</li>
  <li>@('ALWAYS') &nbsp; &mdash; return @('(AND ')<i>val1</i> ... <i>valn</i>@(' T)')</li>
  <li>@('THEREIS') &mdash; return @('(OR ')<i>val1</i> ... <i>valn</i>@(')')</li>
  </ul>

  <p>Note that if <i>op</i> is @('ALWAYS'), iteration can stop the first time a
  <i>vali</i> is @('nil').  Similarly, if <i>op</i> is @('THEREIS'), iteration
  can stop the first time a <i>vali</i> is non-@('nil').  Note also that an
  @('ALWAYS') @('loop$') returns @('NIL') or @('T') but a @('THEREIS')
  @('loop$') returns @('nil') or the first non-@('nil') value produced by the
  evaluation of the body.</p>

  <p>Now go to @(see lp-section-6) (or return to the <see topic='@(url
  lp-section-0)'>Table of Contents</see>).</p>")
other
(defxdoc lp-section-6
  :parents (loop$-primer)
  :short "Challenge Problems about @('FOR') @('Loop$')s"
  :long "<h3>LP6: Challenge Problems about @('FOR') @('Loop$')s</h3>

  <p>The questions below ask you to write and evaluate some @('FOR')
  @('loop$')s at the top-level of ACL2.</p>

  <p>Our answers to the problems in this section are in @(see community-books)
  file @('demos/loop-primer/lp6.lisp').  Feel free to look at our answers after
  you have worked on a problem.  But remember: reading an answer is not as
  helpful as finding it yourself.  If you give up on a problem, look at our
  answer for just that problem, so maybe you take a little more insight into
  your work on subsequent problems.</p>

  <p>Don't forget to start your session by including the standard book for
  @('apply$').</p>

  @({
  (include-book "projects/apply/top" :dir :system)
  })

  <p>Don't bother with adding @(':guard') expressions and don't define any
  functions of your own yet.  All of these questions can be answered by
  @('loop$') expressions involving only ACL2 primitives and the constant
  function @('bags') which we introduce below for convenience.</p>

  <p>Let a &ldquo;bag&rdquo; be a true list of symbols.  The function below returns a
  constant list of bags.  You may use @('(bags)') in your solutions.  Notice
  that some elements of @('(bags)') contain the symbol @('x') and other do
  not.</p>

  @({
  (defun bags ()
    '((a b c)
      (d x e f)
      (g h i x)
      (j)
      (x k l)))
  })

  <p>Here is a sample question and how you might check that your @('loop$')
  computes the expected value.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>Sample Question: Build an alist that pairs the first symbol in every bag
  of @('(bags)') with the number of other symbols in the bag.  The expected
  value is @('((A . 2) (D . 3) (G . 3) (J . 0) (X . 2))').</p>

  <p>Sample Check of a Solution:</p>

  @({
  (equal (loop$ for bag in (bags)
                collect (cons (car bag) (len (cdr bag))))
         '((A . 2) (D . 3) (G . 3) (J . 0) (X . 2)))
  })

  <p>Of course, you could just type the @('loop$') statement at the top-level
  of your ACL2 session and visually inspect the answer.  If you want to
  make a certified book out of your answers we recommend expressing the
  checks as @('defthm') events of @(':rule-classes nil'), as in</p>

  @({
  (defthm check-sample-question
    (equal (loop$ for bag in (bags)
                  collect (cons (car bag) (len (cdr bag))))
           '((A . 2) (D . 3) (G . 3) (J . 0) (X . 2)))
    :rule-classes nil)
  })

  <p>However, if your @('loop$') involves a user-defined function and you
  express your answers as @('defthm')s then each theorem will need to have
  appropriate warrant hypotheses, as illustrated below.</p>

  @({
  (defun my-len (x) (if (atom x) 0 (+ 1 (my-len (cdr x)))))
  (defwarrant my-len)
  (defthm check-my-sample-question
    (implies (warrant my-len)
             (equal (loop$ for bag in (bags)
                           collect (cons (car bag) (my-len (cdr bag))))
                    '((A . 2) (D . 3) (G . 3) (J . 0) (X . 2))))
    :rule-classes nil)
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP6-1:</b> Concatenate all the bags in @('(bags)').</p>

  <p><b>Expected Value:</b>@('(A B C D X E F G H I X J X K L)')</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP6-2:</b> Collect the bags that contain the symbol @('x').</p>

  <p><b>Expected Value:</b>@('((D X E F) (G H I X) (X K L))')</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP6-3:</b> If you used some version of @('member') in your solution to
  LP6-2, now do it without using any version of @('member').</p>

  <p><b>Expected Value:</b>@('((D X E F) (G H I X) (X K L))')</p>

  <p>Don't use any version of @('member') in your answers to the remaining
  questions in this section.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP6-4:</b> Remove all the @('x')s from each bag in @('(bags)') and
  concatenate the resulting bags.</p>

  <p><b>Expected Value:</b>@('(A B C D E F G H I J K L)')</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP6-5:</b> Collect the first symbol of each of the bags in @('(bags)')
  that contains an @('x').</p>

  <p><b>Expected Value:</b>@('(D G X)')</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP6-6:</b> From each bag in @('(bags)'), remove the elements
  preceding the first @('x') and collect the resulting bags.</p>

  <p><b>Expected Value:</b>@('(NIL (X E F) (X) NIL (X K L))')</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP6-7:</b> Let's say the &ldquo;alternating sum of signed squares&rdquo; of a
  list of numbers is the sum of the squares of the elements, except the squares
  of elements in even positions (0-based) are added and the squares in odd
  positions are subtracted.  So the alternating sum of signed squares of @('(1
  2 3 4 5)') is @('(+ 1 -4 9 -16 25)') = @('15').  Compute the alternating sum
  of signed squares of the lengths of the bags in @('(bags)')</p>

  <p><b>Expected Value:</b>@('(+ 9 -16 16 -1 9)') = @('17').</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP6-8:</b> Collect all the function symbols in the current ACL2
  world with an arity greater than 9.</p>

  <p>Three Hints: First, the term @('(function-theory :here)') returns a list
  of the runes of all the @(':logic') mode functions currently in the ACL2
  world.  However, it expands to an expression involving the variable
  @('world') which can be obtained by @('(w state)').  And @(tsee state) may
  not be used in @('FOR') @('loop$')!  So you'll have to @(tsee let) bind
  @('world') to @('(w state)') and write your @('loop$') inside the scope of
  that @('let').</p>

  <p>Second, every @(tsee rune) returned by @('function-theory') is of the form
  @('(:DEFINITION fn . x)'), where @('fn') is the name of a function.</p>

  <p>Third, the arity of a symbol @('fn') is obtained from the world by
  @('(arity fn world)'), except sometimes (for reasons we won't go into!) it
  returns @('nil').</p>

  <p><b>Expected Value:</b> As of ACL2 Version 8.5 (after including the
  @('"projects/apply/top"') book) the answer was @('(MEMOIZE-FORM SEARCH-FN
  SEARCH-FN-GUARD BUILD-STATE1)'), but that may change.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP6-9:</b> Collect the name of every theorem about @('EXPT') in the
  current world.</p>

  <p>Three More Hints: First, the ACL2 world is a list of triples of the form
  @('(name property . val)') representing the current property lists.  In ACL2
  Version 8.5, the length of the world (after including the
  @('"projects/apply/top"') book) is 137,846, so it's too big to just look
  at!</p>

  <p>Second, each event that named a theorem has a triple of the form @('(name
  THEOREM . val)'), where @('name') is the event name and @('val') is the
  translated version of the theorem.  (Thus, you won't find macros like @('+')
  or @('append') in @('val')!  Instead it would contain the function symbols
  appearing in their expansions, e.g., @('binary-+') and @('binary-append').
  But since we're looking for @('expt') and it is not a macro, this doesn't
  matter.)</p>

  <p>Third, the ACL2 term @('(all-fnnames term)') returns a list of all the
  function symbols used in the fully translated term @('term').</p>

  <p><b>Expected Value:</b> As of ACL2 Version 8.5 (after including the
  @('"projects/apply/top"') book) the answer was
  @('(APPLY$-PRIM-META-FN-EV-CONSTRAINT-462 RATIONALP-EXPT-TYPE-PRESCRIPTION
  EXPT-TYPE-PRESCRIPTION-NON-ZERO-BASE)')</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>These exercises highlight three important lessons about
  @('loop$').</p>

  <p>The first is that with @('loop$') you can avoid defining a lot of
  recursive functions.  Imagine doing these same exercises without
  @('loop$').</p>

  <p>The second is that it is not always a good idea to &ldquo;inline&rdquo; @('loop$')s
  instead of defining functions.  The clearest example of that arises above
  when we prohibited you from using @('member')!  Just because @('member') can
  be replaced by a @('loop$') doesn't mean it should be!  @('Member') is an
  exceptionally useful function that enjoys a lot of elegant properties.  By
  introducing the name @('member') and proving its properties we can use it
  conveniently and appeal to those properties often.  Of course, @('member') is
  a Common Lisp primitive, so we're not free to define it, but if we were to
  define a function like that we could use a @('loop$') in its definition.</p>

  <p>Another example of this second lesson is in question LP6-7.  Depending on
  the project at hand, the notion of &ldquo;alternating sum of signed squares&rdquo;
  might be a useful one in its own right.  So perhaps if such a problem came up
  you might define @('(alternating-sum-of-signed-squares lst)'), perhaps using
  @('loop$') in the @('defun'), and then use</p>

  @({
  (alternating-sum-of-signed-squares
    (loop$ for bag in (bags) collect (len bag)))
  })

  <p>to compute the quantity requested in LP6-7.</p>

  <p>The question raised by this second lesson isn't so much whether you use a
  @('loop$') to express the concept but whether you use a @('defun') to give
  the concept a name.  A good rule of thumb is: <i>if the concept has a natural
  name, define it!</i></p>

  <p>Of course, there is the usual trade-off between execution efficiency and
  modularity.  There are various ways to deal with this trade-off in ACL2 but
  since they are not unique to @('loop$') we won't discuss them.</p>

  <p>The third lesson is highlighted by LP6-8 and LP6-9.  @('Loop$') can be
  very useful in extracting data about your current ACL2 session, if you are
  familiar with the ACL2 system-level utilities (see @(see system-utilities)
  for some of them).  Perhaps more relevant is the observation that if you are
  building a big model involving lots of data, you might find @('loop$') handy
  in querying your own data.</p>

  <p>Now go to @(see lp-section-7) (or return to the <see topic='@(url
  lp-section-0)'>Table of Contents</see>).</p>")
other
(defxdoc lp-section-7
  :parents (loop$-primer)
  :short "Using @('Loop$')s and Guards in @('Defun')s"
  :long "<h3>LP7: Using @('Loop$')s and Guards in @('Defun')s</h3>

  <p>@('Loop$') statements are most efficient when they are guard verified.
  @('Loop$')s typed at the top-level are typically not guard verified and so
  they are not executed by running compiled Common Lisp @('loop')s.  Instead,
  their formal semantics is executed which is akin to saying they are
  interpreted.  But execution efficiency was one of the motivational factors in
  the introduction of @('loop$') and that is best achieved by using @('loop$')s
  in guard verified function definitions.</p>

  <p>Here is an example.  We've already discussed @('member') and the fact that
  calls of @('member') can be replaced by @('loop$')s.  @('Member') is a macro
  that expands logically to @('member-equal'), where</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>Let's define an equivalent function, named @('member-equal-loop$'), using
  @('loop$').</p>

  @({
  (defun member-equal-loop$ (x lst)
    (declare (xargs :guard (true-listp lst)))
    (loop$ for tail of-type (satisfies true-listp) on lst
           thereis
           (if (equal x (car tail)) tail nil)))

  (defthm member-equal-loop$-is-member-equal
     (equal (member-equal-loop$ x lst)
            (member-equal x lst)))
  })

  <p>Since @('member-equal') has a guard of @('(true-listp lst)'), we will give
  our @('member-equal-loop$') the same guard.  But in our @('loop$') above we
  also wrote that the iteration variable @('tail') satisfies @('true-listp').
  We do that so that ACL2 can prove the guard on @('(car tail)') in the
  @('thereis') clause.  (We could change ACL2 to infer this type for @('tail')
  in this special case, but more generally we would prefer to have an effective
  heuristic for transferring arbitrary properties of @('lst') to relevant
  properties of @('tail').)</p>

  <p>The guard obligations for @('member-equal-loop$') are obscure because we
  haven't explained the formal semantics of @('loop$') yet.  But we do not
  discuss the guard obligations of @('loop$')s in the primer.  If you define a
  function containing a @('loop$') and try to verify its guards the system will
  generate the necessary obligations and try to prove them.  Our solutions to
  all the exercises in this primer can be guard verified automatically.  For
  more details on @('FOR') @('loop$') guards and the guard obligations they generate,
  see @(see for-loop$), specifically, the sections &ldquo;Special Guard Conjectures
  for @('FOR') @('Loop$')s&rdquo; and &ldquo;Discussion of Why @('Loop$')s Have Special
  Guards.&rdquo;</p>

  <p>After admitting @('member-equal-loop$') ACL2 can prove inductively that it is
  equal to @('member-equal').  We'll come back to that later too.</p>

  <p>An alternative way to specify the type of @('tail') would be to add a @(':guard')
  rather than an @('of-type') expression.</p>

  @({
  (defun member-equal-loop$ (x lst)
    (declare (xargs :guard (true-listp lst)))
    (loop$ for tail on lst
           thereis
           :guard (true-listp tail)
           (if (equal x (car tail)) tail nil)))
  })

  <p>The @(':guard') feature of ACL2 is more flexible than @('of-type') because
  guards allow you to use multiple variables to express a constraint, while
  @('of-type') implicitly limits the assertion to the variable being
  introduced.  For example, with a guard you could say @('(subsetp-equal tail
  lst)') while you cannot express such a constraint with @('of-type').
  However, @('of-type') is understood by the Common Lisp compiler which might
  optimize the compiled code using that type information, while guards are not
  seen by the compiler.</p>

  <p>When you use a @('loop$') in a @('defun') to be guard verified, be sure to
  constrain its iteration variables (and global variables) appropriately so you
  can verify the guards of the body.  (You are also allowed to specify
  different guards for any @('when') and @('until') expressions.)  We generally
  split our constraints between @('of-type') and @(':guard') to inform the
  compiler of simple types, while more elaborate guard conditions are sometimes
  necessary to verify the guards of the body, etc.  ACL2 will take any
  @('of-type') information and conjoin it to any @(':guard') when doing guard
  verification.</p>

  <p>Now go to @(see lp-section-8) (or return to the <see topic='@(url
  lp-section-0)'>Table of Contents</see>).</p>")
other
(defxdoc lp-section-8
  :parents (loop$-primer)
  :short "Challenge Problems about @('FOR') @('Loop$') in @('Defun')s"
  :long "<h3>LP8: Challenge Problems about @('FOR') @('Loop$') in @('Defun')s</h3>

  <p>Do the problems below, starting in a fresh ACL2 session that starts with
  the standard @('(include-book "projects/apply/top" :dir :system)').  Each
  problem starts with one or more recursive functions.  Admit those functions
  in your session.  Then define equivalent versions using @('loop$')s instead
  of recursion.  Make sure each of your @('defun')s is admitted and guard
  verified.  Try to ensure that the @('loop$') version is unconditionally equal
  to the recursive version of each function.  But you might find more elegant
  solutions if you're willing to condition your equivalences on the guards of
  the recursive versions.  After all, a main motivation for using @('loop$') is
  the runtime efficiency of the compiled raw Lisp, and since no ACL2 function
  is executed in raw Lisp unless the guards are verified.</p>

  <p>Finally, you need not use ACL2 to prove that your @('loop$') functions
  correctly implement their recursive counterparts.  But you should be aware
  that with a few exceptions the proofs of our solutions were completely
  automatic.  We'll focus on proving theorems about @('loop$')s later in the
  primer.</p>

  <p>Our answers to the problems in this section are in @(see community-books)
  file @('demos/loop-primer/lp8.lisp').</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>Sample Question:  @('(Sum-vals alist)') sums the value components
  of an alist.  Note its guard.</p>

  @({

  (defun symbol-to-integer-alistp (x)
    (declare (xargs :guard t))
    (if (atom x)
        (equal x nil)
        (and (consp (car x))
             (symbolp (caar x))
             (integerp (cdar x))
             (symbol-to-integer-alistp (cdr x)))))

  (defun sum-vals (alist)
    (declare (xargs :guard (symbol-to-integer-alistp alist)))
    (cond ((endp alist) 0)
          (t (+ (cdar alist) (sum-vals (cdr alist))))))
  })

  <p>E.g., @('(sum-vals '((a . 1) (b . 2) (c . 3))) = 6').</p>

  <p>Define @('sum-vals-loop$') so that it is unconditionally equivalent to
  @('sum-vals') but uses @('loop$') instead of recursion.</p>

  <p>Sample Solution:</p>

  @({
  (defun sum-vals-loop$ (alist)
    (declare (xargs :guard (symbol-to-integer-alistp alist)))
    (loop$ for pair in alist
           sum
           :guard (and (consp pair)
                       (integerp (cdr pair)))
           (cdr pair)))
  })

  <p>The @('(consp pair)') in the @('loop$') @(':guard') is necessary because
  the @('loop$') body contains @('(cdr pair)') and Common Lisp expects @('cdr')
  to be applied to a @('consp') or @('nil').  The @('(integerp (cdr pair))') is
  necessary because the value of the @('loop$') body is being @('sum')med and
  so must be (at least) a number to satisfy Common Lisp's expectation on
  @('+').</p>

  <p>Verification of Sample Solution:</p>

  @({
  (defthm sum-vals-loop$-is-sum-vals
    (equal (sum-vals-loop$ alist)
           (sum-vals alist))
    :rule-classes nil)
  })

  <p>It is conceivable in some Common Lisps that the following would compile
  into more efficient code.</p>

  @({
  (defun sum-vals-loop$ (alist)
    (declare (xargs :guard (symbol-to-integer-alistp alist)))
    (loop$ for pair of-type cons in alist
           sum
           :guard (integerp (cdr pair))
           (the integer (cdr pair))))
  })

  <p>The thinking is that the @('of-type cons') and @('(the integer (cdr
  pair))') could in principle allow the compiler to do type checking that could
  eliminate runtime tests to avoid errors.  That's because @('of-type') and
  @('the') are Common Lisp primitives, as are the particular @(tsee type-spec)s
  used in @('sum-vals-loop$').  Whether such a well-declared version of
  @('sum-vals-loop$') would actually run faster on your Common Lisp depends on
  the compiler and the optimization proclamations.  In CCL and SBCL with ACL2's
  default proclamations, this well-declared version runs no faster than the
  original sample solution does.  We raise this point simply to alert the
  reader to the difference between compiler directives and @(':guard')s.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP8-1</b> Define @('sum-vals-loop$') which is like our solution shown
  for @('sum-vals') above, except instead of using @('symbol-to-integer-alist')
  as the @(':guard') write the @(':guard') as @('(and (true-listp alist) (loop$
  ...))').  Be sure your definition is admitted and guard verified.</p>

  <p>If you want a slightly more challenging problem, omit the @('(true-listp
  alist)') from the @(':guard') and use a @('FOR') @('loop$')
  &ldquo;@('ON')&rdquo; @('alist').  FYI: Common Lisp requires
  &ldquo;@('IN')&rdquo; @('loop$')s to be over a @('true-listp') target, but
  there is no such requirement for &ldquo;@('ON')&rdquo; @('loop$')s.</p>

  <p>You can always convert an &ldquo;@('IN')&rdquo; @('loop$') governed by a
  @('true-listp') check to an &ldquo;@('ON')&rdquo; @('loop$') without the
  check.  See our solutions.  But because of that, we'll use the more elegant
  &ldquo;@('IN')&rdquo; solutions in the rest of these problems.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP8-2</b> The recursive function below is in the ACL2
  sources (therefore, you will not have to define it in your session).  Define
  an equivalent function, named @('arglistp1-loop$') that uses @('loop$')
  instead of recursion.</p>

  @({
  (defun arglistp1 (lst)
    (declare (xargs :guard t))
    (cond ((atom lst) (null lst))
          (t (and (legal-variablep (car lst))
                  (arglistp1 (cdr lst))))))
  })

  <p>Why is @('arglistp1-loop$') a little less efficient than @('arglistp')?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP8-3</b> The two recursive functions below are used in the ACL2
  sources (thus, you won't have to define them in your session).  Define
  @('packn1-loop$') that is equivalent to @('packn1') but so that it uses
  @('loop$')s and does not mention @('atom-listp').</p>

  @({
  (defun atom-listp (lst)
    (declare (xargs :guard t
                    :mode :logic))
    (cond ((atom lst) (eq lst nil))
          (t (and (atom (car lst))
                  (atom-listp (cdr lst))))))

  (defun packn1 (lst)
    (declare (xargs :guard (atom-listp lst)))
    (cond ((endp lst) nil)
          (t (append (explode-atom (car lst) 10)
                     (packn1 (cdr lst))))))
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;


  <p><b>LP8-4</b>  Define @('select-corresponding-element-loop$') so that it
  is equivalent to @('select-corresponding-element'), below, but using a
  @('loop$') statement.</p>

  @({
  (defun select-corresponding-element (e lst1 lst2)
    (declare (xargs :guard (and (true-listp lst1)
                                (true-listp lst2)
                                (not (member nil lst2)))))
    (cond
     ((endp lst1) nil)
     ((endp lst2) nil)
     ((equal e (car lst1)) (car lst2))
     (t (select-corresponding-element e (cdr lst1) (cdr lst2)))))
  })

  <p>For example,</p>

  @({
  (select-corresponding-element
    'wednesday
    '(sunday monday tueday wednesday thursday friday saturday)
    '(dimanche lundi mardi mercredi jeudi vendredi samedi))
  =
  'MERCREDI
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP8-5</b> Define @('same-mod-wildcard-loop$') to be equivalent to
  @('same-mod-wildcard'), below, but using a @('loop$') statement.</p>

  @({
  (defun same-mod-wildcard (lst1 lst2)
    (declare (xargs :guard (and (true-listp lst1)
                                (true-listp lst2)
                                (equal (len lst1) (len lst2)))))
    (cond ((endp lst1) t)
          ((or (eq (car lst1) '*)
               (eq (car lst2) '*))
           (same-mod-wildcard (cdr lst1) (cdr lst2)))
          ((equal (car lst1) (car lst2))
           (same-mod-wildcard (cdr lst1) (cdr lst2)))
          (t nil)))
  })

  <p>For example,</p>
  @({
  (same-mod-wildcard '(a * c d *) '(a x c * d))
  =
  T
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP8-6</b> The following function is part of the ACL2 source code, so you
  don't have to define it in your session.</p>

  @({
  (defun getprops1 (alist)
    (declare (xargs :guard (true-list-listp alist)))
    (cond ((endp alist) nil)
          ((or (null (cdar alist))
               (eq (car (cdar alist))
                   *acl2-property-unbound*))
           (getprops1 (cdr alist)))
          (t (cons (cons (caar alist) (cadar alist))
                   (getprops1 (cdr alist))))))
  })

  <p>Define @('getprops1-loop$') to do the same thing using @('loop$').</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>Now go to @(see lp-section-9) (or return to the <see topic='@(url
  lp-section-0)'>Table of Contents</see>).</p>")
other
(defxdoc lp-section-9
  :parents (loop$-primer)
  :short "Semantics of @('FOR') @('Loop$')s"
  :long "<h3>LP9: Semantics of @('FOR') @('Loop$')s</h3>

  <p>For a thorough discussion of the semantics of @('FOR') @('loop$')s see
  @(see for-loop$), specifically the section &ldquo;Semantics&rdquo; which
  includes two subsections, &ldquo;Semantics of Simple @('Loop$')s&rdquo; and
  &ldquo;Semantics of Fancy @('Loop$')s.&rdquo; &ldquo;Fancy&rdquo; @('FOR')
  @('loop$')s are @('FOR') @('loop$')s involving multiple iteration variables
  and/or use of &ldquo;global&rdquo; (i.e., non-iteration) variables in the
  @('loop$') body or the @('until') or @('when') clauses. We discuss @('DO')
  @('loop$')s later.  In this section of the primer we just present some
  examples to drive home a few important points about @('FOR') @('loop$')s,
  namely</p>

  <ul>

  <li>The semantics of a @('loop$') statement is obtained by translating the
  @('loop$') statement, as with the command @(':')@(tsee trans).</li>

  <li>However, translation inserts a lot of tags into the formal term it
  produced.  These tags allow us to execute @('loop$') statements more
  efficiently in the top-level ACL2 read-eval-print @('loop$').  The tags on a
  translated @('loop$'), <i>term</i>, can be removed by the @(':')@(tsee
  tc) (&ldquo;translate and clean&rdquo;) command and its variants @(':tca')
  and @(':tcp').  When we exhibit semantics we typically show these simplified,
  equivalent terms produced by one of these commands.</li>

  <li>The semantics of @('FOR') @('loop$')s look quite different from the
  semantics of @('DO') @('loop$')s.  Furthermore, the semantics of simple
  @('loop$')s have a different form than those of fancy @('loop$').  So
  &ldquo;minor&rdquo; changes in the syntax of a @('loop$') statement &mdash; the
  addition of an @('AS') clause, the use of global variable in the body of the
  @('loop$'), or the use of @('DO') instead of, say, @('collect') &mdash; can
  cause radical changes in the form of the semantics.</li>

  <li>The semantics of @('loop$')s always involve calls of @(tsee scion)s on
  lambda objects derived from the @('when'), @('until'), and @('loop$') body
  clauses.  The scions for simple @('FOR') @('loop$')s are @('sum$'),
  @('collect$'), @('always$'), @('thereis$'), @('append$'), @('until$'), and
  @('when$'); the scions for fancy @('FOR') @('loop$')s are @('sum$+'),
  @('collect$+'), @('always$+'), @('thereis$+'), @('append$+'), @('until$+'),
  and @('when$+'); and the scion for @('DO') @('loop$')s is @('do$').</li>

  <li>The iteration variables become formals of the @('lambda') objects and
  standard names are used in place of the user's names.</li>

  </ul>

  <p>Now we drive home these points with some examples.  The <see topic='@(url
  lp-section-10)'>next section</see> elaborates further.</p>

  <p>Here is the full, formal translation of a simple @('FOR') @('loop$').</p>

  @({
  ACL2 !>:trans (loop$ for x of-type integer in lst
                       when (evenp x)
                       collect (* x x))

  (RETURN-LAST
   'PROGN
   '(LOOP$ FOR X OF-TYPE INTEGER IN LST
           WHEN (EVENP X)
           COLLECT (* X X))
   (COLLECT$
     '(LAMBDA (LOOP$-IVAR)
              (DECLARE (TYPE INTEGER LOOP$-IVAR)
                       (XARGS :GUARD (INTEGERP LOOP$-IVAR)
                              :SPLIT-TYPES T)
                       (IGNORABLE LOOP$-IVAR))
              (RETURN-LAST 'PROGN
                           '(LAMBDA$ (LOOP$-IVAR)
                                     (DECLARE (TYPE INTEGER LOOP$-IVAR))
                                     (LET ((X LOOP$-IVAR))
                                          (DECLARE (IGNORABLE X))
                                          (* X X)))
                           ((LAMBDA (X) (BINARY-* X X))
                            LOOP$-IVAR)))
     (WHEN$ '(LAMBDA (LOOP$-IVAR)
                     (DECLARE (TYPE INTEGER LOOP$-IVAR)
                              (XARGS :GUARD (INTEGERP LOOP$-IVAR)
                                     :SPLIT-TYPES T)
                              (IGNORABLE LOOP$-IVAR))
                     (RETURN-LAST 'PROGN
                                  '(LAMBDA$ (LOOP$-IVAR)
                                            (DECLARE (TYPE INTEGER LOOP$-IVAR))
                                            (LET ((X LOOP$-IVAR))
                                                 (DECLARE (IGNORABLE X))
                                                 (EVENP X)))
                                  ((LAMBDA (X) (EVENP X)) LOOP$-IVAR)))
            LST)))
  })

  <p>However, the logical meaning of this is easier to understand by
  looking at one of the @('tc') variations.</p>

  @({
  ACL2 !>:tc (loop$ for x of-type integer in lst
                        when (evenp x)
                        collect (* x x))
   (COLLECT$ '(LAMBDA (LOOP$-IVAR)
                      (BINARY-* LOOP$-IVAR LOOP$-IVAR))
             (WHEN$ '(LAMBDA (LOOP$-IVAR) (EVENP LOOP$-IVAR))
                    LST))
  ACL2 !>:tcp (loop$ for x of-type integer in lst
                         when (evenp x)
                         collect (* x x))
   (COLLECT$ (LAMBDA$ (LOOP$-IVAR)
                      (* LOOP$-IVAR LOOP$-IVAR))
             (WHEN$ (LAMBDA$ (LOOP$-IVAR)
                             (EVENP LOOP$-IVAR))
                    LST))
  ACL2 !>:tca (loop$ for x of-type integer in lst
                         when (evenp x)
                         collect (* x x))
   (PROG2$
     '(LOOP$ FOR X OF-TYPE INTEGER IN LST
             WHEN (EVENP X)
             COLLECT (* X X))
     (COLLECT$ (LAMBDA$ (LOOP$-IVAR)
                  (DECLARE (TYPE INTEGER LOOP$-IVAR)
                           (XARGS :GUARD (INTEGERP LOOP$-IVAR)
                                  :SPLIT-TYPES T))
                  (LET ((X LOOP$-IVAR))
                       (* X X)))
               (WHEN$ (LAMBDA$ (LOOP$-IVAR)
                         (DECLARE (TYPE INTEGER LOOP$-IVAR)
                                  (XARGS :GUARD (INTEGERP LOOP$-IVAR)
                                         :SPLIT-TYPES T))
                         (LET ((X LOOP$-IVAR))
                              (EVENP X)))
                      LST)))
  })

  <p>Note that @(':tc') prints the term generated by translating the @('loop$')
  and then removing all tags.  The guard and type declarations are logically
  irrelevant.  What you see is what the theorem prover will see
  (if all the necessary warrants are assumed) before it starts to rewrite the
  term.  Note that the @('lambda') object is just a quoted list constant and
  the body has been translated so that the @('*') macro was expanded in terms
  of @('binary-*').</p>

  <p>@(':Tcp') (&ldquo;p&rdquo; for &ldquo;pretty&rdquo;) introduces familiar system macros.</p>

  <p>@(':Tca') (&ldquo;a&rdquo; for &ldquo;annotations&rdquo;) includes the original @('loop$')
  statement and shows declarations (if any) and the correspondence between the
  user's iteration variable (@('x') here) and the formal variable used in the
  @('lambda') objects generated (@('loop$-ivar') here).</p>

  <p>The translation of @('loop$') bodies into @('lambda') objects standardizes
  the variable name, either as @('loop$-ivar') for simple @('loop$')s which
  have just one iteration variable, or as @('loop$-gvars') and @('loop$-ivars')
  for fancy @('loop$')s which may have one or more global variables and one or
  more iteration variables.  We'll deal with fancy @('loop$')s immediately
  below, but values are passed for @('loop$-gvars') and @('loop$-ivars') as tuples
  listing all the global values and all the current iteration variable
  values.</p>

  <p>The advantage of this standardization is that choosing different names for
  the iteration variables does not affect the formal semantics.</p>

  <p>However, if we make a simple syntactic change, like introducing a global
  variable by changing the body of the loop$ from @('(* x x)') to @('(* x a)'),
  where @('a') is not an iteration variable, we drastically change the
  semantics because we've converted the simple @('loop$') into a fancy
  @('loop$').  The (clean and pretty) semantics of</p>

  @({
  (loop$ for x in lst when (evenp x) collect (* x a))
  })

  <p>is</p>

  @({
  (COLLECT$+ (LAMBDA$ (LOOP$-GVARS LOOP$-IVARS)
                      (* (CAR LOOP$-IVARS) (CAR LOOP$-GVARS)))
             (LIST A)
             (WHEN$+ (LAMBDA$ (LOOP$-GVARS LOOP$-IVARS)
                              (EVENP (CAR LOOP$-IVARS)))
                     NIL
                     (LOOP$-AS (LIST LST))))
  })

  <p>The annotated semantics of that @('loop$') is</p>

  @({
  (PROG2$
   '(LOOP$ FOR X IN LST
           WHEN (EVENP X)
           COLLECT (* X A))
   (COLLECT$+
     (LAMBDA$ (LOOP$-GVARS LOOP$-IVARS)
              (DECLARE (XARGS :GUARD (AND (TRUE-LISTP LOOP$-GVARS)
                                          (EQUAL (LEN LOOP$-GVARS) 1)
                                          (TRUE-LISTP LOOP$-IVARS)
                                          (EQUAL (LEN LOOP$-IVARS) 1))
                              :SPLIT-TYPES T))
              (LET ((A (CAR LOOP$-GVARS))
                    (X (CAR LOOP$-IVARS)))
                   (* X A)))
     (LIST A)
     (WHEN$+ (LAMBDA$ (LOOP$-GVARS LOOP$-IVARS)
                      (DECLARE (XARGS :GUARD (AND (TRUE-LISTP LOOP$-GVARS)
                                                  (EQUAL (LEN LOOP$-GVARS) 0)
                                                  (TRUE-LISTP LOOP$-IVARS)
                                                  (EQUAL (LEN LOOP$-IVARS) 1))
                                      :SPLIT-TYPES T))
                      (LET ((X (CAR LOOP$-IVARS)))
                           (EVENP X)))
             NIL
             (LOOP$-AS (LIST LST)))))
  })

  <p>Logically, we could have typed either of the above terms instead of the
  fancy @('loop$').  But operationally, the @('loop$') executes faster (when
  guards are verified).</p>

  <p>Notice that the simple scions @('COLLECT$') and @('WHEN$') have been
  replaced by their fancy counterparts, @('COLLECT$+') and @('WHEN$+').  The
  @('lambda') objects now have two formals, one for holding a tuple containing
  all of the global variable values and one for a tuple holding all of the
  current iteration variable values.  The global variable value tuple, @('(LIST
  A)'), is passed into the fancy scions if the corresponding @('lambda') object
  uses globals (as for the @('collect$+') but not for the @('when$+')
  @('lambda') where @('NIL') is passed instead).  The list over which the
  iteration variable ranges, @('LST'), is now a list of tuples constructed by
  @('LOOP$-AS').  Finally, the bodies of the @('lambda')s now access the
  relevant values with @('CAR') and @('CDR') nests around the global and
  iteration tuples. (No @('CDR')s appear above because there is only one global
  and one iteration variable in this example.)</p>

  <p>The following similar but still fancier @('loop$') illustrates the general
  situation.  This @('loop$') has two iteration variables, @('x') and @('y')
  taking on values from two ranges, @('xlst'), and @('ylst'), and uses two
  global variables, @('a') and @('b'), in the body.  We've added comments to
  name the components of the two tuples.</p>

  @({
  ACL2 !>:tcp (loop$ for x in xlst
                     as  y in ylst
                     when (evenp x)
                     collect (* x y a b))
   (COLLECT$+ (LAMBDA$ (LOOP$-GVARS LOOP$-IVARS)
                       (* (CAR LOOP$-IVARS)               ; x
                          (CADR LOOP$-IVARS)              ; y
                          (CAR LOOP$-GVARS)               ; a
                          (CADR LOOP$-GVARS)))            ; b
              (LIST A B)
              (WHEN$+ (LAMBDA$ (LOOP$-GVARS LOOP$-IVARS)
                               (EVENP (CAR LOOP$-IVARS))) ; x
                      NIL
                      (LOOP$-AS (LIST XLST YLST))))
  })

  <p>Notice how the bodies of the @('lambda') objects now use components of the
  @('loop$-gvars') and @('loop$-ivars)') for the current values of the global
  variables @('a') and @('b') and the iteration variables @('x') and @('y').
  The values of @('x') and @('y') are corresponding elements of @('xlst') and
  @('ylst') as grouped together by @('(loop$-as (list xlst ylst))').</p>

  <p>For a still-more elaborate @('FOR') @('loop$') and a step-by-step
  description of how the value of the formal semantics is computed, go to @(see
  lp-section-10).</p>

  <p>Now go to @(see lp-section-10) (or return to the <see topic='@(url
  lp-section-0)'>Table of Contents</see>).</p>")
other
(defxdoc lp-section-10
  :parents (loop$-primer)
  :short "The Evaluation of the Formal Semantics of a Fancy @('Loop$')"
  :long "<h3>LP10: The Evaluation of the Formal Semantics of a Fancy @('Loop$')</h3>

  <p>Below we show the evaluation of a fancy @('loop$') that uses the function
  @('packn') to create a list of symbols.  We start with an example of
  @('packn') so you can infer its behavior.  But our real interest is the
  behavior of the @('loop$').</p>

  @({
  ACL2 !>(packn (list 'R2 '- 'D 2))
  R2-D2
  ACL2 !>(let ((mark '*))
           (loop$ for x in '(a * b c d e * f g h i j * k)
                  as  y in '(u v * w * u v * x y z)
                  as  i from 0 to 100 by 3
                  when (and (evenp i)
                            (not (eq x mark))
                            (not (eq y mark)))
                  collect (packn (list x y '_ i))))
  (AU_0 GX_24 IZ_30)
  ACL2 !>
  })

  <p>We now explain carefully the evaluation of the @('loop$') expression above
  in an environment in which @('mark') is bound to the asterisk symbol,
  @('*').</p>

  <p>The first three lines of the @('loop$') introduce the so-called <i>iteration
  variables</i>, @('x'), @('y'), and @('i'), and their respective
  <i>ranges</i>.</p>

  <p>The @('when') clause specifies a predicate on the iteration variables,
  identifying the &ldquo;good&rdquo; cases, i.e., the values of the iteration variables
  that we care about.  However, note that the predicate above mentions the
  variable @('mark'), which is not one of the iteration variables.  We call
  such variables <i>globals</i> because their values are not set within the
  scope of the @('loop').</p>

  <p>The @('collect') clause specifies an expression to be evaluated on the
  &ldquo;good&rdquo; iteration variable values and collects the results of those
  evaluations.</p>

  <p>If you replace the symbol @('loop$') above by @('loop') you get a legal
  Common Lisp @('loop') expression with the same value (if executed when
  @('mark') is bound to @('*')).</p>

  <p>For our purposes, the easiest way to think about this particular statement
  is to decompose it into three steps.</p>

  <p>Step 1: The lines introducing the iteration variables and their ranges
  cause us to make a table of corresponding values of @('x'), @('y'), and
  @('i'), as shown below in the form of a list of triples.  This list is as
  long as the shortest individual range.</p>

  @({
  ; x y  i
  ((A U  0)
   (* V  3)
   (B *  6)
   (C W  9)
   (D * 12)
   (E U 15)
   (* V 18)
   (F * 21)
   (G X 24)
   (H Y 27)
   (I Z 30)).
  })

  <p>Step 2: the @('when') clause maps over the above table and identifies the
  entries as &ldquo;good&rdquo; or &ldquo;bad&rdquo;, where the good ones have an even value for
  @('i') and values for @('x') and @('y') that are not the asterisk mark,
  @('*').  We annotate the table accordingly below.</p>

  @({
  ; x y  i
  ((A U  0)        ; GOOD!
   (* V  3)        ; bad: odd i (and asterisk)
   (B *  6)        ; bad: asterisk
   (C W  9)        ; bad: odd i
   (D * 12)        ; bad: asterisk
   (E U 15)        ; bad: odd i
   (* V 18)        ; bad: asterisk
   (F * 21)        ; bad: odd i (and asterisk)
   (G X 24)        ; GOOD!
   (H Y 27)        ; bad: odd i
   (I Z 30)).      ; GOOD!
  })

  <p>Effectively the @('when') clause pares down the table to just the good
  entries.</p>

  @({
  ; x y  i
  ((A U  0)        ; GOOD!
   (G X 24)        ; GOOD!
   (I Z 30)).      ; GOOD!
  })

  <p>Step 3: the @('collect') clause maps over pared-down table, evaluating and
  collecting the results of @('(packn (list x y '_ i))') for each triple in the
  table.</p>

  @({
  (AU_0
   GX_24
   IZ_30).
  })

  <p>The ACL2 semantics of the @('loop$') statement reflects this understanding
  of the statement.  (The display below is the output of @(':tca') on the
  @('loop$'), but with the @('DECLARE') forms deleted and the three comments
  added.)</p>

  @({
  (collect$+                                        ; step 3
   (lambda$ (loop$-gvars loop$-ivars)
            (let ((x (car loop$-ivars))
                  (y (cadr loop$-ivars))
                  (i (caddr loop$-ivars)))
              (packn (list x y '_ i))))
   nil
   (when$+                                          ; step 2
    (lambda$ (loop$-gvars loop$-ivars)
             (let ((mark (car loop$-gvars))
                   (x (car loop$-ivars))
                   (y (cadr loop$-ivars))
                   (i (caddr loop$-ivars)))
               (and (evenp i)
                    (not (eq x mark))
		    (not (eq y mark)))))
    (list mark)
    (loop$-as (list '(a * b c d e * f g h i j * k)  ; step 1
                    '(u v * w * u v * x y z)
                    (from-to-by 0 100 3)))))
  })

  <p>In step 1, the @('loop$-as') function takes a list of the individual
  ranges and builds the first version of the iteration variable table.  The
  function @('from-to-by') just enumerates the integers from its first argument
  to its second argument in steps of size given by its third argument.</p>

  <p>In step 2, the @('when$+') function takes three arguments.  Note that the
  last argument of the @('when$+') function is the iteration variable table
  computed by step 1.  The first argument of the @('when$+') function is a
  @('lambda$') expression representing the predicate used to identify the
  &ldquo;good&rdquo; entries.  But that predicate may also require the value of any
  global variables used.  So the @('lambda$') expression has two arguments,
  @('loop$-gvars'), the list of values of the global variables, and
  @('loop$-ivars'), a tuple of values corresponding to a line in the iteration
  variable table.  The middle argument of the @('when$+') provides the values
  of the global variables and, as noted earlier, the last argument is the
  iteration variable table.  The @('when$+') maps over the iteration variable
  table and collects the &ldquo;good&rdquo; lines, returning them as a list.</p>

  <p>In step 3, the @('collect$+') takes three arguments.  The first is a
  @('lambda$') expression on the @('loop$-gvars') and @('loop$-ivars') as
  above.  The second and third arguments are the global variable values and the
  &ldquo;good&rdquo; lines from the pared-down iteration variable table as computed by
  step 2.  Note that since the @('collect') clause does not mention any global
  variables the global variable tuple in the second argument of the
  @('collect$+') is @('nil').</p>

  <p>Of course, Common Lisp does not decompose the corresponding @('loop')
  statement this way but generates much more efficient compiled code.</p>

  <p>The ACL2 semantics is rendered compositionally to make it easier to reason
  about @('loop$') statements.  If the guards of the @('loop$') statement
  &mdash; which we haven't discussed yet &mdash; are verified then the ACL2
  loop$ statement is rendered into the corresponding Common Lisp @('loop')
  statement, compiled, and efficiently executed.</p>

  <p>Now go to @(see lp-section-11) (or return to the <see topic='@(url
  lp-section-0)'>Table of Contents</see>).</p>")
other
(defxdoc lp-section-11
  :parents (loop$-primer)
  :short "Proving Theorems about @('FOR') @('Loop$')s"
  :long "<h3>LP11: Proving Theorems about @('FOR') @('Loop$')s</h3>

  <p>Proving theorems about @('FOR') @('loop$') in ACL2 is essentially no
  different than proving theorems about other constructs in ACL2.  Indeed,
  since @('loop$')s turn into calls of @(see scion)s of @(tsee apply$), proving
  things about them is exactly the problem of proving things about scions.
  However, @('loop$')s raise some problems that are not fully technical.</p>

  <ul>

  <li>Iteration is so common in programming &mdash; and the meaning of
  @('loop$') statements are intuitively obvious &mdash; that you often don't
  think anything logically complicated is going on!  But when proofs are
  desired you must keep induction in mind and you must train yourself to see
  the need for generalization in order to allow the necessary inductions.</li>

  <li>You're not syntactically aware of the presence of @('apply$') and the
  concomitant need for @(see tame)ness and @(see warrant)s.</li>

  <li>You don't see the translations of @('loop$')s when you type them but they
  appear &ldquo;unexpectedly&rdquo; in the checkpoints of failing proofs and that can
  throw you for a loop (so to speak).</li>

  <li>The translations of @('loop$')s, especially of fancy @('loop$'), are
  pretty complicated in and of themselves and can be difficult to understand,
  much less generalize and manipulate formally.</li>

  <li>The ACL2 user rarely has to think about local variable bindings, but
  those issues arise quite often in dealing with loop$s (and nested @('lambda')
  objects in general).</li>

  </ul>

  <p>With these points in mind we will now work through a proof about a fancy
  @('loop$').  In the next section we'll challenge you to do some proofs about
  other @('loop$')s.  The proof description below is rather long because we
  cast it as a narrative of the proof discovery process and the actual
  chronology of events submitted, including failed events and our thoughts
  about the failures.</p>

  <p>Sample Question: Define the function @('all-pairs') recursively so that
  @('(all-pairs imax jmax)') creates a list of all pairs @('(i . j)') where
  @('1 <= i <= imax') and @('1 <= j <= jmax').  Then define the @('loop$')
  version of @('all-pairs') and prove it is equivalent to @('all-pairs').
  Both versions must be guard verified.</p>

  <p>Sample Solution (as a narrative of the discovery).</p>

  <p>As usual, we make sure we're operating in a session where</p>

  @({(include-book "projects/apply/top" :dir :system)})

  <p>We will construct our pairs with</p>

  @({
  (defun make-pair (i j)
    (declare (xargs :guard t))
    (cons i j))
  })

  <p>Here is our recursive definition.  It involves two helper functions.
  @('All-pairs-helper2') keeps @('i') fixed and runs @('j') from @('1') to
  @('jmax') to compute the list of pairs @('((i . 1) (i . 2) ... (i . jmax))').
  @('All-pairs-helper1') just calls the former helper for each @('i') from
  @('1') to @('imax') and appends the lists together.  The top-level
  @('all-pairs') calls @('all-pairs-helper1') with @('i') properly initialized
  to @('1').</p>

  @({
  (defun all-pairs-helper2 (i j jmax)
    (declare (xargs :measure (nfix (- (+ (nfix jmax) 1) (nfix j)))
                    :guard (and (natp i) (natp j) (natp jmax))))
    (let ((j (nfix j))
          (jmax (nfix jmax)))
      (cond
       ((> j jmax) nil)
       (t (cons (make-pair i j)
                (all-pairs-helper2 i (+ 1 j) jmax))))))

  (defun all-pairs-helper1 (i imax jmax)
    (declare (xargs :measure (nfix (- (+ (nfix imax) 1) (nfix i)))
                    :guard (and (natp i) (natp imax) (natp jmax))))
    (let ((i (nfix i))
          (imax (nfix imax)))
      (cond
       ((> i imax) nil)
       (t (append (all-pairs-helper2 i 1 jmax)
                  (all-pairs-helper1 (+ 1 i) imax jmax))))))

  (defun all-pairs (imax jmax)
    (declare (xargs :guard (and (natp imax) (natp jmax))))
    (all-pairs-helper1 1 imax jmax))
  })

  <p>Here is a simple test.</p>

  @({
  ACL2 !>(all-pairs 2 4)
  ((1 . 1)
   (1 . 2)
   (1 . 3)
   (1 . 4)
   (2 . 1)
   (2 . 2)
   (2 . 3)
   (2 . 4))
  })

  <p>And here is our first attempt to define the @('loop$') version, which is
  considerably &ldquo;simpler&rdquo; (or, at least, shorter).  But this will fail!  Can
  you say why without reading the error message?</p>

  @({
  (defun all-pairs-loop$ (imax jmax)
    (declare (xargs :guard (and (natp imax) (natp jmax))))
    (loop$ for i from 1 to imax
           append
           (loop$ for j from 1 to jmax
                  collect (make-pair i j))))

  ACL2 Error [Translate] in ( DEFUN ALL-PAIRS-LOOP$ ...):  The body of
  a LAMBDA object, lambda$ term, or loop$ statement should be fully badged
  but MAKE-PAIR is used in
  ((LAMBDA (I J) (MAKE-PAIR I J)) (CAR LOOP$-GVARS) (CAR LOOP$-IVARS))
  and has no badge. ...
  ... Note:  this error occurred in the context
  (LAMBDA$ (LOOP$-GVARS LOOP$-IVARS)
           (DECLARE (XARGS :GUARD (AND (TRUE-LISTP LOOP$-GVARS)
                                       (EQUAL # 1)
                                       (TRUE-LISTP LOOP$-IVARS)
                                      (EQUAL # 1))))
           (LET ((I (CAR LOOP$-GVARS))
                 (J (CAR LOOP$-IVARS)))
                (DECLARE (IGNORABLE I J))
                (MAKE-PAIR I J))).
  })

  <p>The error message above includes some extraneous possible explanation of
  the error which we've omitted.</p>

  <p>The error tells us we forgot to assign a badge to @('make-pair').  We
  could call @('(defbadge make-pair)') at this point.  But since we intend to
  prove things about @('all-pairs-loop$') we'll actually need the warrant for
  the @('make-pair'), since @('make-pair') is user-defined and is used in the body of a
  @('loop$').  So we'll go ahead and create the warrant.</p>

  @({
  (defwarrant make-pair)
  })

  <p>(Had we just badged @('make-pair') at this point and proceeded another
  error message would crop up in due course and tell us to warrant it.)</p>

  <p>Trying the @('defun') again causes another failure with the checkpoint
  shown below.</p>

  @({
  (defun all-pairs-loop$ (imax jmax)
    (declare (xargs :guard (and (natp imax) (natp jmax))))
    (loop$ for i from 1 to imax
           append
           (loop$ for j from 1 to jmax
                  collect (make-pair i j))))

  *** Key checkpoint at the top level: ***

  Subgoal 1.2'
  (IMPLIES (AND (CONSP LOOP$-IVARS)
                (NOT (CDR LOOP$-IVARS))
                (CONSP LOOP$-GVARS)
                (NOT (CDR LOOP$-GVARS)))
           (INTEGERP (CAR LOOP$-GVARS)))

  ACL2 Error [Failure] in ( DEFUN ALL-PAIRS-LOOP$ ...):  The proof of
  the guard conjecture for ALL-PAIRS-LOOP$ has failed; see the discussion
  above about :VERIFY-GUARDS and :GUARD-DEBUG.  See :DOC failure.
  })

  <p>We need to prove, as part of the guard verification, that @('(CAR
  LOOP$-GVARS)') is an integer.  At this point we might want to refresh our
  idea of what the formal semantics of that nested loop$ is!</p>

  <p>We do not recommend using @(':trans') for that refreshment!  You can try
  it and you'll see 67 lines of output with a lot of extra stuff in it used to
  help evaluate such forms efficiently.  Instead we'll use
  @(':tca') (&ldquo;translate, clean, and annotate&rdquo;) which produces about half as
  much output and shows the original form of each @('loop$') together with
  formal semantics, complete with @(':guard') declarations on the @('LAMBDA')
  objects and correspondences between the variable names used in the original
  statement with the components of the formals @('LOOP$-GVARS') and
  @('LOOP$-IVARS') in the @('lambda$') terms generated.</p>

  <p>(Note: We have manually inserted some comments to identify certain lines
  of the display below.)</p>

  @({
  ACL2 !>:tca (loop$ for i from 1 to imax
                     append
                     (loop$ for j from 1 to jmax
                            collect (make-pair i j)))
  (PROG2$
    '(LOOP$ FOR I FROM 1 TO IMAX
            APPEND
            (LOOP$ FOR J FROM 1 TO JMAX
                   COLLECT (MAKE-PAIR I J)))
    (APPEND$+                                                      ; [0]
     (LAMBDA$ (LOOP$-GVARS LOOP$-IVARS)                            ; [1]
       (DECLARE (XARGS :GUARD (AND (TRUE-LISTP LOOP$-GVARS)        ; [2]
                                   (EQUAL (LEN LOOP$-GVARS) 1)
                                   (TRUE-LISTP LOOP$-IVARS)
                                   (EQUAL (LEN LOOP$-IVARS) 1))
                       :SPLIT-TYPES T))
       (LET ((JMAX (CAR LOOP$-GVARS))                              ; [3]
             (I (CAR LOOP$-IVARS)))
         (PROG2$
          '(LOOP$ FOR J FROM 1 TO JMAX COLLECT (MAKE-PAIR I J))
          (COLLECT$+
           (LAMBDA$ (LOOP$-GVARS LOOP$-IVARS)
             (DECLARE (XARGS :GUARD (AND (TRUE-LISTP LOOP$-GVARS)
                                         (EQUAL (LEN LOOP$-GVARS) 1)
                                         (TRUE-LISTP LOOP$-IVARS)
                                         (EQUAL (LEN LOOP$-IVARS) 1))
                             :SPLIT-TYPES T))
             (LET ((I (CAR LOOP$-GVARS))
                   (J (CAR LOOP$-IVARS)))
               (MAKE-PAIR I J)))
           (LIST I)
           (LOOP$-AS (LIST (FROM-TO-BY 1 JMAX 1)))))))             ; [4]
     (LIST JMAX)                                                   ; [5]
     (LOOP$-AS (LIST (FROM-TO-BY 1 IMAX 1)))))                     ; [6]
  })

  <p>We're trying to verify the guards all the functions in that expression,
  and we have the @(':guard') in the @('defun') of @('all-pairs-loop$') to work
  with.  That @(':guard') is @('(and (natp imax) (natp jmax))').</p>

  <p>So what functions above require an argument to be an integer?  Hint: There
  is only one such function but it occurs in two places.</p>

  <p>@('From-to-by') requires all three of its arguments to be integers and
  that function appears on lines [4] and [6].  Line [4] requires @('jmax') to
  be an integer and line [6] requires @('imax') to be an integer.  But line [6]
  is the formal term representing the &ldquo;@('from 1 to imax')&rdquo; range of the
  @('append') @('loop$') formalized with the fancy scion @('APPEND$+') at line
  [0].  That @('imax') is literally the first formal variable of the defun of
  @('all-pairs-loop$') whose @(':guard') says @('imax') and @('jmax') are a
  naturals.  So [6] is not the problem.</p>

  <p>The @('jmax') in line [4], on the other hand, is actually a @('let')-bound
  variable (see line [3]) within the @('lambda') object (line [1]) that is the
  body of the @('append') loop$ [line 0].  @('jmax') is bound inside that
  @('lambda') on line [3] to @('(car loop$-gvars)') and the @(':guard') (line
  [2]) of that @('lambda') does not require @('(car loop$-gvars)') to be an
  integer.  We need to add that requirement to [2].</p>

  <p>So how do we change the @(':guard') of a @('lambda') generated by the
  translation of the @('append') @('loop$')?  We add &ldquo;@(':guard (natp
  jmax)')&rdquo; after the @('append') operator.  (Note that @('(integerp jmax)')
  would suffice here but we added the stronger condition ensured by the
  @('all-pairs-loop$')'s guard.)</p>

  <p>Using @(':tca') again on the modified @('loop$') confirms our change.</p>

  @({
  ACL2 !>:tca (loop$ for i from 1 to imax
                          append
                          :guard (natp jmax)                   ; [new]
                          (loop$ for j from 1 to jmax
                                 collect (make-pair i j)))
  (PROG2$
    '(LOOP$ FOR I FROM 1 TO IMAX
            APPEND
            (LOOP$ FOR J FROM 1 TO JMAX
                   COLLECT (MAKE-PAIR I J)))
    (APPEND$+                                                  ; [0]
     (LAMBDA$ (LOOP$-GVARS LOOP$-IVARS)                        ; [1]
       (DECLARE (XARGS :GUARD (AND (TRUE-LISTP LOOP$-GVARS)    ; [2']
                                   (EQUAL (LEN LOOP$-GVARS) 1)
                                   (TRUE-LISTP LOOP$-IVARS)
                                   (EQUAL (LEN LOOP$-IVARS) 1)
                                   (NATP (CAR LOOP$-GVARS)))   ; [new]
                       :SPLIT-TYPES T))
       (LET ((JMAX (CAR LOOP$-GVARS))                          ; [3]
             (I (CAR LOOP$-IVARS)))
         (PROG2$
          '(LOOP$ FOR J FROM 1 TO JMAX COLLECT (MAKE-PAIR I J))
          (COLLECT$+
           (LAMBDA$ (LOOP$-GVARS LOOP$-IVARS)
             (DECLARE (XARGS :GUARD (AND (TRUE-LISTP LOOP$-GVARS)
                                         (EQUAL (LEN LOOP$-GVARS) 1)
                                         (TRUE-LISTP LOOP$-IVARS)
                                         (EQUAL (LEN LOOP$-IVARS) 1))
                             :SPLIT-TYPES T))
             (LET ((I (CAR LOOP$-GVARS))
                   (J (CAR LOOP$-IVARS)))
               (MAKE-PAIR I J)))
           (LIST I)
           (LOOP$-AS (LIST (FROM-TO-BY 1 JMAX 1)))))))         ; [4]
     (LIST JMAX)                                               ; [5]
     (LOOP$-AS (LIST (FROM-TO-BY 1 IMAX 1)))))                 ; [6]
  })

  <p>Observe the difference between the @(':guard') on the original line [2]
  and the @(':guard') on the new line [2'].  The latter includes @('(natp (car
  loop$-gvars))').</p>

  <p>If we think in terms of scions, we're saying &ldquo;Every time this @('lambda')
  object is applied, its two formals must satisfy the conjunction beginning at
  line [2'].&rdquo;</p>

  <p>Finally, how do we know every application of the @('lambda') by the fancy
  scion @('append$+') (line [0]) will satisfy this guard?  We know from the
  definition of @('append$+') that every application supplies the @('(list
  jmax)') from line [5] as the value of @('loop$-gvars').  That occurrence of
  @('jmax') is at the top-level of the body and in the scope of the guard of
  @('all-pairs-loop$'), which says @('jmax') is a natural.  So the guards can
  be proved now.</p>

  <p>So now we can admit and verify the guards of our @('loop$') version of
  @('all-pairs').</p>

  @({
  (defun all-pairs-loop$ (imax jmax)
    (declare (xargs :guard (and (natp imax) (natp jmax))))
    (loop$ for i from 1 to imax
           append
           :guard (natp jmax)
           (loop$ for j from 1 to jmax
                  collect (make-pair i j))))
  })

  <p>Our goal is to prove the theorem below.  We use @(see The-Method), with
  which we assume you're familiar but which we narrate below.</p>

  <p>First we try to prove our main goal.  It fails with the checkpoint
  shown.</p>

  @({
  (defthm main
    (implies (and (natp imax)
                  (natp jmax))
             (equal (all-pairs-loop$ imax jmax)
                    (all-pairs imax jmax))))

  *** Key checkpoint at the top level: ***

  Goal''
  (IMPLIES
   (AND (INTEGERP IMAX)
        (<= 0 IMAX)
        (INTEGERP JMAX)
        (<= 0 JMAX))
   (EQUAL
    (APPEND$+
     (LAMBDA$ (LOOP$-GVARS LOOP$-IVARS)
              (COLLECT$+ (LAMBDA$ (LOOP$-GVARS LOOP$-IVARS)
                                  (CONS (CAR LOOP$-GVARS)
                                        (CAR LOOP$-IVARS)))
                         (LIST (CAR LOOP$-IVARS))
                         (LOOP$-AS (LIST (FROM-TO-BY 1 (CAR LOOP$-GVARS) 1)))))
     (LIST JMAX)
     (LOOP$-AS (LIST (FROM-TO-BY 1 IMAX 1))))
    (ALL-PAIRS-HELPER1 1 IMAX JMAX)))
  })

  <p>Looking at the conclusion we see need to prove that the @('append$+') term
  is equal to the @('all-pairs-helper1') term.  From our ACL2 experience with
  recursive functions like @('all-pairs-helper1') we know this is an inductive
  proof.  But no induction is suggested by @('(all-pairs-helper1 1 imax jmax)')
  because the constant @('1') is in a controller position.  We need to
  generalize the @('1') by replacing it with @('i0'), a general initial value
  of @('i').  Note that we replace the @('1') in two places, namely, the first
  @('1') in @('(loop$-as (list (from-to-by 1 imax 1)))'), and the @('1') in
  @('(all-pairs-helper1 1 imax jmax)').  Those two @('1')s are the concrete
  initial values of two @('i') counters on opposite sides of the equality.
  There are three other occurrences of the number @('1') in the conjecture.
  The first one is the initial value of the variable @('j'), the second is the
  step size for counting up from @('j') to @('jmax'), and the third one is the
  step size for counting up from @('i') to @('imax').  We do not change those
  three occurrences of @('i').</p>

  <p>We submit the proposed generalization as @('lemma1').  The conclusion of
  @('lemma1') is exactly the equality conclusion above except for the
  replacement of those two @('1')s by the new variable @('i0').  The hypothesis
  of @('lemma1') requires all the variables to be naturals.  But the proof
  attempt fails!  The checkpoint is shown below.</p>

  @({
  (defthm lemma1
    (implies
     (and (natp imax)
          (natp jmax)
          (natp i0))
     (equal
      (append$+
       (lambda$ (loop$-gvars loop$-ivars)
                (collect$+ (lambda$ (loop$-gvars loop$-ivars)
                                    (cons (car loop$-gvars)
                                          (car loop$-ivars)))
                           (list (car loop$-ivars))
                           (loop$-as (list (from-to-by 1 (car loop$-gvars) 1)))))
       (list jmax)
       (loop$-as (list (from-to-by i0 imax 1))))
      (all-pairs-helper1 i0 imax jmax))))

  *** Key checkpoint under a top-level induction: ***

  Subgoal *1/6''
  (IMPLIES
   (AND
    (<= I0 IMAX)
    (EQUAL
     (APPEND$+
         (LAMBDA$
              (LOOP$-GVARS LOOP$-IVARS)
              (COLLECT$+ (LAMBDA$ (LOOP$-GVARS LOOP$-IVARS)
                                  (CONS (CAR LOOP$-GVARS)
                                        (CAR LOOP$-IVARS)))
                         (LIST (CAR LOOP$-IVARS))
                         (LOOP$-AS (LIST (FROM-TO-BY 1 (CAR LOOP$-GVARS) 1)))))
         (LIST JMAX)
         (LOOP$-AS (LIST (FROM-TO-BY (+ 1 I0) IMAX 1))))
     (ALL-PAIRS-HELPER1 (+ 1 I0) IMAX JMAX))
    (INTEGERP IMAX)
    (<= 0 IMAX)
    (INTEGERP JMAX)
    (<= 0 JMAX)
    (INTEGERP I0)
    (<= 0 I0))
   (EQUAL (APPEND (COLLECT$+ (LAMBDA$ (LOOP$-GVARS LOOP$-IVARS)
                                      (CONS (CAR LOOP$-GVARS)
                                            (CAR LOOP$-IVARS)))
                             (LIST I0)
                             (LOOP$-AS (LIST (FROM-TO-BY 1 JMAX 1))))
                  (ALL-PAIRS-HELPER1 (+ 1 I0) IMAX JMAX))
          (APPEND (ALL-PAIRS-HELPER2 I0 1 JMAX)
                  (ALL-PAIRS-HELPER1 (+ 1 I0) IMAX JMAX))))
  })

  <p>Notice that we're trying to prove something of the form</p>

  @({
  (EQUAL (APPEND a1 b1)
         (APPEND a2 b2))
  })

  <p>where @('b1') and @('b2') are identical.  So we will prove @('(EQUAL a1
  a2)').</p>

  <p>But again, this is inductive.  The @('(from-to-by 1 jmax 1)') and the
  @('(all-pairs-helper2 i0 1 jmax)') are both counting up from @('1') as the
  initial value of @('j').  We need to generalize those @('1')s to @('j0').
  So we submit the following as @('lemma2').  And it succeeds!</p>

  @({
  (defthm lemma2
    (implies (and (natp imax)
                  (natp jmax)
                  (natp i0)
                  (natp j0))
             (equal (collect$+ (lambda$ (loop$-gvars loop$-ivars)
                                        (cons (car loop$-gvars)
                                              (car loop$-ivars)))
                               (list i0)
                               (loop$-as (list (from-to-by j0 jmax 1))))
                    (all-pairs-helper2 i0 j0 jmax))))
  })

  <p>So now we return to @('lemma1'), whose checkpoint suggested @('lemma2').
  But it fails again, this time with a different checkpoint</p>

  @({
  (defthm lemma1
    (implies
     (and (natp imax)
          (natp jmax)
          (natp i0))
     (equal
      (append$+
       (lambda$ (loop$-gvars loop$-ivars)
                (collect$+ (lambda$ (loop$-gvars loop$-ivars)
                                    (cons (car loop$-gvars)
                                          (car loop$-ivars)))
                           (list (car loop$-ivars))
                           (loop$-as (list (from-to-by 1 (car loop$-gvars) 1)))))
       (list jmax)
       (loop$-as (list (from-to-by i0 imax 1))))
      (all-pairs-helper1 i0 imax jmax))))

  *** Key checkpoint at the top level: ***

  [1]Goal
  (APPLY$-WARRANT-COLLECT$+)
  })

  <p>Note that this checkpoint comes from a forcing round (the clue is the
  &ldquo;@('[1]') prefix to the @('Goal')), which means the proof succeeded except
  for some hypotheses that were forced so that certain lemmas could fire and
  now have to be proved.  But the hypothesis above is the warrant for
  @('collect$+').  We need the warrant for @('collect$+') because that function
  is being applied with @('apply$') every time @('append$+') iterates.  This is
  easy to fix.  We just add the warrant as a hypothesis to @('lemma1').</p>

  @({
  (defthm lemma1
    (IMPLIES
     (AND (warrant collect$+)
          (natp imax)
          (natp jmax)
          (natp i0))
     (equal
      (append$+
       (lambda$ (loop$-gvars loop$-ivars)
                (collect$+ (lambda$ (loop$-gvars loop$-ivars)
                                    (cons (car loop$-gvars)
                                          (car loop$-ivars)))
                           (list (car loop$-ivars))
                           (loop$-as (list (from-to-by 1 (car loop$-gvars) 1)))))
       (list jmax)
       (loop$-as (list (from-to-by i0 imax 1))))
      (all-pairs-helper1 i0 imax jmax))))
  })

  <p>This proof succeeds.</p>

  <p>So now we return to @('main').  By the way, because we expect the theorem
  to be proved by applying @('lemma1'), we provide the hint that tells the
  prover not to even try induction.  This just reduces the output if the proof
  fails.</p>

  <p>Unfortunately this attempt fails, but with two easy-to-fix
  checkpoints.</p>

  @({
  (defthm main
    (implies (and (natp imax)
                  (natp jmax))
             (equal (all-pairs-loop$ imax jmax)
                    (all-pairs imax jmax)))
    :hints (("Goal" :do-not-induct t)))

  *** Key checkpoints at the top level: ***

  [1]Subgoal 2
  (APPLY$-WARRANT-MAKE-PAIR)

  [1]Subgoal 1
  (APPLY$-WARRANT-COLLECT$+)
  })

  <p>Note that the checkpoints are forcing round subgoals showing that we need
  two warrants.  So we add both warrants to @('main')'s hypotheses.  And we're
  done.</p>

  @({
  (defthm main
    (implies (and (warrant collect$+ make-pair)
                  (natp imax)
                  (natp jmax))
             (equal (all-pairs-loop$ imax jmax)
                    (all-pairs imax jmax)))
    :hints (("Goal" :do-not-induct t)))
  })

  <p>Note: The @(':do-not-induct') hint could be deleted because the theorem is
  proved without appealing to induction anyway.</p>

  <p>You might wonder why we need the warrant on @('make-pairs').  It never arose in any
  checkpoint except in the very last failed proof.</p>

  <p>The first time we tried to prove @('main') we failed, and got this checkpoint.</p>

  @({
  Goal''
  (IMPLIES
   (AND (INTEGERP IMAX)
        (<= 0 IMAX)
        (INTEGERP JMAX)
        (<= 0 JMAX))
   (EQUAL
    (APPEND$+
     (LAMBDA$ (LOOP$-GVARS LOOP$-IVARS)
              (COLLECT$+ (LAMBDA$ (LOOP$-GVARS LOOP$-IVARS)
                                  (CONS (CAR LOOP$-GVARS)
                                        (CAR LOOP$-IVARS)))
                         (LIST (CAR LOOP$-IVARS))
                         (LOOP$-AS (LIST (FROM-TO-BY 1 (CAR LOOP$-GVARS) 1)))))
     (LIST JMAX)
     (LOOP$-AS (LIST (FROM-TO-BY 1 IMAX 1))))
    (ALL-PAIRS-HELPER1 1 IMAX JMAX)))
  })

  <p>The innermost @('lambda$') is the body of the innermost @('loop$')
  statement, @('(loop$ for j from 1 to jmax collect (make-pair i j))'), except
  it has been simplified by the expansion of @('(make-pair i j)') to @('(cons i
  j)').  That expansion of @('make-pair') inside a @('lambda$') required the
  warrant for @('make-pair') and that was forced to produce the @('cons').</p>

  <p>Had that first proof attempt at @('main') succeeded except for that forced
  subgoal, a forcing round would have brought to our attention the need for the
  warrant on @('make-pair').  But that proof attempt failed because the prover could not
  do a suitable induction to prove @('Goal''').  Indeed, that is what led us to @('lemma1').</p>

  <p>But forced subgoals are not reported if the proof fails for other reasons.
  So we were left unaware that we were depending on the warrant for
  @('make-pair').  In the penultimate failed proof @('main') just above, the
  same forced expansion of @('make-pair') occurred and this time the proof
  succeeded except for the forced subgoals requiring warrants for
  @('make-pair') and @('collect$+').  That finally brought the @('make-pair')
  expansion to our attention.</p>

  <p>The more experienced ACL2 user would have noticed (indeed, did notice!)
  the expansion of @('make-pair') in @('Goal''') above and understood the
  warrant for @('make-pair') was needed but wanted to see what would happen if
  that fact was overlooked.</p>

  <p>The final series of events to solve this problem is shown below.</p>

  @({
  ; Include standard apply$ book.
  (include-book "projects/apply/top" :dir :system)

  ; Define and verify the guards of the recursive all-pairs.
  (defun make-pair (i j)
    (declare (xargs :guard t))
    (cons i j))

  (defun all-pairs-helper2 (i j jmax)
    (declare (xargs :measure (nfix (- (+ (nfix jmax) 1) (nfix j)))
                    :guard (and (natp i) (natp j) (natp jmax))))
    (let ((j (nfix j))
          (jmax (nfix jmax)))
      (cond
       ((> j jmax) nil)
       (t (cons (make-pair i j)
                (all-pairs-helper2 i (+ 1 j) jmax))))))

  (defun all-pairs-helper1 (i imax jmax)
    (declare (xargs :measure (nfix (- (+ (nfix imax) 1) (nfix i)))
                    :guard (and (natp i) (natp imax) (natp jmax))))
    (let ((i (nfix i))
          (imax (nfix imax)))
      (cond
       ((> i imax) nil)
       (t (append (all-pairs-helper2 i 1 jmax)
                  (all-pairs-helper1 (+ 1 i) imax jmax))))))

  (defun all-pairs (imax jmax)
    (declare (xargs :guard (and (natp imax) (natp jmax))))
    (all-pairs-helper1 1 imax jmax))

  ; Warrant make-pair so we can use it in a loop$.
  (defwarrant make-pair)

  ; Define and verify the guards of the loop$ version.
  (defun all-pairs-loop$ (imax jmax)
    (declare (xargs :guard (and (natp imax) (natp jmax))))
    (loop$ for i from 1 to imax
           append
           :guard (natp jmax)
           (loop$ for j from 1 to jmax
                  collect (make-pair i j))))

  ; Prove that the generalized inner loop$ is all-pairs-helper2.
  (defthm lemma2
    (implies (and (natp imax)
                  (natp jmax)
                  (natp i0)
                  (natp j0))
             (equal (collect$+ (lambda$ (loop$-gvars loop$-ivars)
                                        (cons (car loop$-gvars)
                                              (car loop$-ivars)))
                               (list i0)
                               (loop$-as (list (from-to-by j0 jmax 1))))
                    (all-pairs-helper2 i0 j0 jmax))))

  ; Prove that the generalized outer loop$ is all-pairs-helper1.
  (defthm lemma1
    (implies
     (and (warrant collect$+)
          (natp imax)
          (natp jmax)
          (natp i0))
     (equal
      (append$+
       (lambda$ (loop$-gvars loop$-ivars)
                (collect$+ (lambda$ (loop$-gvars loop$-ivars)
                                    (cons (car loop$-gvars)
                                          (car loop$-ivars)))
                           (list (car loop$-ivars))
                           (loop$-as (list (from-to-by 1 (car loop$-gvars) 1)))))
       (list jmax)
       (loop$-as (list (from-to-by i0 imax 1))))
      (all-pairs-helper1 i0 imax jmax))))

  ; Main theorem
  (defthm main
    (implies (and (warrant collect$+ make-pair)
                  (natp imax)
                  (natp jmax))
             (equal (all-pairs-loop$ imax jmax)
                    (all-pairs imax jmax))))
  })

  <p>Now go to @(see lp-section-12) (or return to the <see topic='@(url
  lp-section-0)'>Table of Contents</see>).</p>")
other
(defxdoc lp-section-12
  :parents (loop$-primer)
  :short "Challenge Proof Problems about @('FOR') @('Loop$')s"
  :long "<h3>LP12: Challenge Proof Problems about @('FOR') @('Loop$')s</h3>

  <p>If you have not already, warm up by proving the correctness of your
  solutions to the problems in @(see lp-section-8).</p>

  <p>Remember to operate in a session in which you have included the
  standard @('loop$') book.</p>

  @({
  (include-book "projects/apply/top" :dir :system)
  })

  <p>Our answers to the problems in @(see lp-section-8) are in @(see
  community-books) file @('demos/loop-primer/lp8.lisp'), and our answers to the
  problems below are in @(see community-books) file
  @('demos/loop-primer/lp12.lisp').</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP12-1</b> Define @('(assoc-equal-loop$ x alist)') to be equal to
  @('(assoc-equal x alist)') when @('(alistp alist)').  Verify the guards of
  @('assoc-equal-loop$') and prove that your function satisfies the
  specification above.  Is your function in fact unconditionally equal to
  @('assoc-equal')?  If so, prove it; if not, show a counterexample.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP12-2</b> Under what conditions is the following a theorem?  Fill in
  the blank and prove the theorem.</p>

  @({
  (defthm LP12-2
    (implies ...
             (equal (loop$ for x in keys as y in vals collect (cons x y))
                    (pairlis$ keys vals)))
    :rule-classes nil)
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP12-3</b> Prove</p>

  @({
  (defthm LP12-3
    (equal (* 2 (len (loop$ for tl on lst append tl)))
           (* (len lst) (+ (len lst) 1))))
  })

  <p><i>Hint:</i> By phrasing the challenge with the multiplication by 2 on the
  left-hand side, we produce a conjecture that can be proved (perhaps with a
  few lemmas) without the need for &ldquo;heavy duty&rdquo; arithmetic books.  Had we
  divided by 2 on the right-hand side, we'd have brought division into the
  problem which we intentionally avoided.  You will still need a lemma or two,
  discoverable by The Method.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP12-4</b>  Define</p>

  @({
  (defun nats (n)
    (cond ((zp n) (list 0))
          (t (append (nats (- n 1)) (list n)))))
  })

  <p>and prove that the obvious @('loop$') statement is equivalent to @('(nats
  n)') when @('n') is a natural.  Make your @('defthm') have @(':rule-classes
  nil') so as not to interfere with your work on the next problem.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP12-5</b> Define</p>

  @({
  (defun nats-up (i n)
    (declare (xargs :measure (nfix (- (+ (nfix n) 1) (nfix i)))))
    (let ((i (nfix i))
          (n (nfix n)))
      (cond ((> i n) nil)
            (t (cons i (nats-up (+ i 1) n))))))
  })

  <p>Prove</p>

  @({
  (defthm LP12-5
    (implies (natp n)
             (equal (loop$ for i from 0 to n collect i)
                    (nats-up 0 n)))
    :rule-classes nil)
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP12-6</b> Fill in the blanks below and prove the theorem.  You may
  need hints.  If not, just delete the :hints setting.</p>

  @({
  (defthm LP12-6
    (implies (true-listp lst)
             (equal (loop$ ...)
                    (strip-cars lst)))
    :hints ...
    :rule-classes nil)
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP12-7</b> Prove the following, adding hints if necessary.  Otherwise,
  just delete the @(':hints') setting.</p>

  @({
  (defthm LP12-7
    (loop$ for pair in (loop$ for key in keys
                              as  val from 0 to (+ (len keys) -1)
                              collect (cons key val))
           always (integerp (cdr pair)))
    :hints ...)
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP12-8</b>  Fill in the blanks below and then prove the theorem.  You may
  need hints.  If not, just delete the @(':hints') setting.</p>

  @({
  (defthm LP12-8
    (implies (natp n)
             (equal (loop$ ...)
                    (nth n lst)))
    :hints ...
    :rule-classes nil)
  })

  <p>Now go to @(see lp-section-13) (or return to the <see topic='@(url
  lp-section-0)'>Table of Contents</see>).</p>")
other
(defxdoc lp-section-13
  :parents (loop$-primer)
  :short "Examples of @('DO') @('Loop$')s"
  :long "<h3>LP13: Examples of @('DO') @('Loop$')s</h3>

  <p>Below is a log of an ACL2 session demonstrating the behavior of a few
  @('DO') @('loop$')s.  As usual with @('loop$')s, one should always work in a
  session in which the book shown below is included.  The examples below do not
  illustrate guards or proofs about @('DO') @('loop$')s.</p>

  <p>We'll describe the syntax and semantics of @('DO') @('loop$')s later.  But
  we expect you can intuit the syntax and semantics of these @('loop$')
  statements from these examples.  The following may help if you're
  unfamiliar with the following Common Lisp primitives.</p>

  <p>In ACL2, <b>These primitives may only be used within @('DO') @('loop$')s!</b></p>

  <ul>

  <li>@('(RETURN ')<i>expr</i>@(')') terminates the @('loop$') and returns
  the value of <i>expr</i> as the value.</li>

  <li>@('(SETQ ')<i>var&nbsp;expr</i>@(')') evaluates <i>expr</i> and assigns the
  value to the variable <i>var</i>.  Parallel assignment with @('mv-setq') is also
  supported but not illustrated here.</li>

  <li>@('(PROGN ')<i>stmt_1 &hellip; stmt_n</i>@(')') evaluates each
  <i>stmt_i</i> in turn and returns the value of the last one.</li>

  <li>@('(LOOP-FINISH)') terminates the iteration in the @('loop$') and passes
  control to the @('FINALLY') clause, if any.</li>

  </ul>

  <p>We start the session with the following commands, whose output we do not
  display here.  Note that we use @(tsee defstobj) to introduce a
  single-threaded object, @('st'), with one field, @('fld1').  We initialize
  @('(fld1 st)') to 0. In addition, we warrant two of the functions introduced
  by the @(tsee defstobj).  We warrant those functions because they are
  user-defined @(':logic') mode functions that we'll use in a @('DO')
  @('loop$').  @('Defstobj') does not automatically badge or warrant the
  functions it defines but they are warrantable.</p>

  @({
  (include-book "projects/apply/top" :dir :system)
  (defstobj st fld1)
  (update-fld1 0 st)
  (defwarrant fld1)
  (defwarrant update-fld1)
  })

  <p>So having set up our session, we now experiment with @('DO')
  @('loop$')s.</p>

  @({

  ; Reverse the elements of the initial value of temp.

  ACL2 !>(loop$ with temp = '(a b c)
                with  ans = nil
                do
                (cond ((endp temp) (return ans))
                      (t (progn (setq ans (cons (car temp) ans))
                                (setq temp (cdr temp))))))
  (C B A)

  ; Reverse the elements of lst down to the first xxx, or return
  ; not-found if there is no xxx in lst.

  ACL2 !>(defun reverse-to-xxx (lst)
           (loop$ with temp = lst
                  with  ans = nil
                  do
                  (cond ((endp temp) (return 'not-found))
                        (t (progn (cond ((eq (car temp) 'xxx) (loop-finish))
                                        (t (setq ans (cons (car temp) ans))))
                                  (setq temp (cdr temp)))))
                  finally
                  (return ans)))

  Since REVERSE-TO-XXX is non-recursive, its admission is trivial.  We
  could deduce no constraints on the type of REVERSE-TO-XXX.

  Summary
  Form:  ( DEFUN REVERSE-TO-XXX ...)
  Rules: NIL
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   REVERSE-TO-XXX

  ACL2 !>(reverse-to-xxx '(a b c xxx d e f))
  (C B A)

  ACL2 !>(reverse-to-xxx '(a b c d e f))
  NOT-FOUND

  ; In the next example we will reverse the elements of the initial value of
  ; temp, except for the xxx's which we just drop but count.  We use (fld1 st)
  ; to store the accumulated count.  This loop$ returns the reversed elements
  ; and the final value of st.  But first we'll show that (fld1 st) is
  ; initially 0.

  ACL2 !>(fld1 st)
  0

  ACL2 !>(loop$ with temp = '(a b c xxx d e xxx f g)
                with ans = nil
                do
                :values (nil st)
                (cond ((endp temp) (return (mv ans st)))
                      (t (progn
                           (cond ((eq (car temp) 'xxx)
                                  (setq st (update-fld1 (+ 1 (fld1 st)) st)))
                                 (t (setq ans (cons (car temp) ans))))
                           (setq temp (cdr temp))))))
  ((G F E D C B A) <st>)

  ACL2 !>(fld1 st)
  2
  })

  <p>We included the last example showing that stobjs can be used inside of
  @('DO') @('loop$')s just to alert you to that feature.  However, in the rest
  of this primer we do not deal with stobjs in @('loop$') because there is
  enough to cover without that!</p>

  <p>See the ACL2 documentation topic @(see DO-loop$) for a more thorough
  discussion of @('DO') @('loop$')s.</p>

  <p>Now go to @(see lp-section-14) (or return to the <see topic='@(url
  lp-section-0)'>Table of Contents</see>).</p>")
other
(defxdoc lp-section-14
  :parents (loop$-primer)
  :short "Challenge Problems about @('DO') @('Loop$')s"
  :long "<h3>LP14: Challenge Problems about @('DO') @('Loop$')s</h3>

  <p>In this section you'll be asked to write and evaluate some @('DO')
  @('loop$')s based entirely on the examples given in the previous section.
  We'll deal with termination, guards, proofs, etc., later.</p>

  <p>We want all iteration in your answers to be done with @('DO') @('loop$')s
  even if the problem could be solved with a @('FOR') @('loop$').</p>

  <p>Our answers to the problems in this section are in @(see community-books)
  file @('demos/loop-primer/lp14.lisp').</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP14-1:</b> Make a list of the integers from 10 down to 0.</p>

  <p><b>Expected Value:</b>@('(10 9 8 7 6 5 4 3 2 1 0)')</p>

  <p>Ok, we know this is a silly question if taken literally!  Why use
  iteration at all if the answer is a constant?  If you want to cheat,
  just enter</p>

  @({
  (loop$ with ans = '(10 9 8 7 6 5 4 3 2 1 0) do (return ans))
  })

  <p>But the spirit of these questions is to use iteration and, if it helps,
  imagine we'd asked you to write a @('loop$') that returns the list of
  integers from 1000000 down to 0!</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP14-2:</b> Sum the naturals less than or equal to 100.</p>

  <p><b>Expected Value:</b> @('5050')</p>

  <p>Hint: Write the @('loop$') so that it counts down!  If you count up you'll
  have to provide a measure term, which can be done by including @(':measure')
  <i>measure-term</i> immediately after the @('DO') operand and before the
  body.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP14-3:</b> Sum the squares of the naturals less than or equal to 100,
  using the following function to square.</p>

  @({
  (defun sq (x) (* x x))
  })

  <p><b>Expected Value:</b> @('338350')</p>


  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP14-4:</b> Write a @('DO') that finds the first occurrence of the
  symbol @('XXX') in the list @(''(A B C XXX D E F)') and returns the tail of
  the list starting with that occurrence.</p>

  <p><b>Expected Value:</b> @('(XXX D E F)')</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP14-5:</b> Fill in the blank below so that the next form is a theorem.
  You do not have to prove the theorem (but it shouldn't be hard).</p>

  @({
  (defun do-loop$-member (e lst)
    (loop$ ...))

  (defthm lp14-5
    (equal (do-loop$-member e lst)
           (member e lst))
    :rule-classes nil)
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP14-6:</b> Given the following</p>

  @({
  (defun steps-for-member (e lst steps)
    (cond ((endp lst) (list steps nil))
          ((equal (car lst) e) (list steps lst))
          (t (steps-for-member e (cdr lst) (+ 1 steps)))))
  })

  <p>fill in the blank so that this is a theorem.</p>

  @({
  (defthm lp14-6
    (equal (loop$ ...)
           (steps-for-member e lst steps))
    :rule-classes nil)
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP14-7:</b>Write a @('DO') to compute the list of all pairs @('(i
  . j)') such that 1 &le; @('i') &le; 3 and 1 &le; @('j') &le; 4.</p>

  <p><b>Expected Value:</b></p>

  @({
  ((1 . 1)
   (1 . 2)
   (1 . 3)
   (1 . 4)
   (2 . 1)
   (2 . 2)
   (2 . 3)
   (2 . 4)
   (3 . 1)
   (3 . 2)
   (3 . 3)
   (3 . 4))
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>Now go to @(see lp-section-15) (or return to the <see topic='@(url
  lp-section-0)'>Table of Contents</see>).</p>")
other
(defxdoc lp-section-15
  :parents (loop$-primer)
  :short "Informal Syntax and Semantics of @('DO') @('Loop$')s"
  :long "<h3>LP15: Informal Syntax and Semantics of @('DO') @('Loop$')s</h3>

  <p>The &ldquo;most elaborate&rdquo; @('DO') @('loop$') looks like this.</p>

  @({
  (LOOP$ WITH var1 OF-TYPE spec1 = init1 ; a WITH declaration
         WITH var2 OF-TYPE spec2 = init2
         ...
         DO
         :measure m
         :guard do-guard
         :values v
         do-body
         FINALLY
         :guard fin-guard
         fin-body)
   })

  <p>where much of that is optional: &ldquo;@('OF-TYPE speci')&rdquo;,
  &ldquo;@('= initi')&rdquo; (when &ldquo;@('OF-TYPE speci')&rdquo; is
  present), &ldquo;@(':MEASURE m')&rdquo;, the two &ldquo;@(':GUARD')
  ...&rdquo; clauses, &ldquo;@(':VALUES v')&rdquo;, and &ldquo;@('FINALLY
  fin-body')&rdquo;.  If the @(':MEASURE') is omitted, ACL2 tries to guess a
  likely measure using the same heuristic it does with recursive @(tsee
  defun)s.  If @(':VALUES') is omitted then @('v') defaults to @('(nil)').</p>

  <p>All ACL2 function symbols in @('m'), @('do-body'), and @('fin-body') must
  be @(see badge)d so @(tsee apply$) can handle them.  Furthermore, they must
  be @(see warrant)ed if proofs are to be done about them or if they are in
  @(see logic) mode and are called during evaluation.</p>

  <p>As you've already inferred from our examples, @('do-body') and
  @('fin-body') are not normal ACL2 terms!  They allow restricted uses of
  @('RETURN'), @('PROGN'), @('SETQ'), @('MV-SETQ'), and @('LOOP-FINISH').</p>

  <p>As for semantics, every legal @('DO') @('loop$') translates into a term
  of the form</p>

  @({
  (DO$ m-lambda
       alist
       do-body-lambda
       fin-body-lambda
       a5
       a6)
  })

  <p>where @('m-lambda'), @('do-body-lambda'), and @('fin-body-lambda') are
  quoted @('LAMBDA') objects derived from the respective terms in the
  @('loop$') statement.  @('Alist') is an association list that maps the
  variables of those terms to their initial values.  We discuss the other three
  arguments later.</p>

  <p>All three of these @('LAMBDA') objects operate on @('alist').  The
  @('m-lambda') may return a natural, and otherwise must return a list of naturals which is treated as a
  lexicographic tuple whose first component is the most significant.  The other
  two @('LAMBDA') objects return a triple of the form @('(exit-token value
  new-alist)').  The @('exit-token') is @(':RETURN'), @(':LOOP-FINISH'), or
  @('NIL'), and indicates what happens next: the @('value') is to be returned
  as the value of the @('loop$'), the @('fin-body-lambda') is to be applied to
  the @('new-alist'), or the @('loop$') is to iterate again on @('new-alist').
  But before the iteration, the @('m-lambda') is applied to the @('new-alist')
  and must be of smaller measure according to @(tsee L<) for iteration to
  continue.</p>

  <p>If the given measure fails to decrease, then, logically speaking, @('a5')
  is used to compute a default answer.  (That argument is actually the output
  signature of the @('loop$') specifying how many values are to be returned and
  whether each value is an ordinary object, a double-float, or a @(see stobj).)
  However, in execution, an error is signaled if the measure fails to decrease.
  Such runtime errors (including @('OF-TYPE') and guard violations if guards
  are being checked) are reported using @('a6') which is just a
  quoted constant about the original @('loop$') statement.  (In fact, @('a6')
  is logically irrelevant and the theorem prover replaces quoted non-@('nil')
  final argument to @('do$') by @('nil') in proofs as part of the cleaning-up
  process.)</p>

  <p>Consider this simple @('DO') @('loop$') and its cleaned-up semantics as
  shown by the @(':')@(tsee tcp) command.  (We have re-pretty-printed it
  to add comments and highlight some symmetries.)</p>

  @({
  ACL2 !>:tcp (loop$ with i = n
                     with ans = 0
                     do
                     (if (zp i)
                         (return ans)
                         (progn (setq ans (+ 1 ans))
                                (setq i (- i 1)))))
   (DO$
;    measure lambda:
     (LAMBDA$ (ALIST)
       (ACL2-COUNT (CDR (ASSOC-EQ-SAFE 'I ALIST))))

;    initial alist:
     (LIST (CONS 'I N)
           (CONS 'ANS 0))

;    do-body lambda:
     (LAMBDA$ (ALIST)
       (IF (ZP (CDR (ASSOC-EQ-SAFE 'I ALIST)))
           (LIST :RETURN
                 (CDR (ASSOC-EQ-SAFE 'ANS ALIST))
                 (LIST (CONS 'I (CDR (ASSOC-EQ-SAFE 'I ALIST)))
                       (CONS 'ANS (CDR (ASSOC-EQ-SAFE 'ANS ALIST)))))
           (LIST NIL
                 NIL
                 (LIST (CONS 'I (+ -1 (CDR (ASSOC-EQ-SAFE 'I ALIST))))
                       (CONS 'ANS (+ 1 (CDR (ASSOC-EQ-SAFE 'ANS ALIST))))))))

;    fin-body lambda (irrelevant here)
     (LAMBDA$ (ALIST)
       (LIST NIL
             NIL
             (LIST (CONS 'I (CDR (ASSOC-EQ-SAFE 'I ALIST)))
                   (CONS 'ANS (CDR (ASSOC-EQ-SAFE 'ANS ALIST))))))

;    irrelevant args a5 and a6
     '(NIL) NIL)
  })

  <p>@('ASSOC-EQ-SAFE') is just @('ASSOC-EQ') with a slightly weaker guard.
  Think of @('(CDR (ASSOC-EQ-SAFE 'var ALIST))') as the current value of the
  local variable @('var').  The measure is that the @('ACL2-COUNT') of the
  current value of @('I') decreases.  The output of the @('do-body')
  @('lambda') is a triple.  The true branch of the @('IF') indicate iteration
  is to stop and return the current value of @('ANS').  The false branch
  indicates iteration is to continue with the new alist given as the third
  element of the triple.  The @('fin-body') @('lambda') is irrelevant because
  there is no @(':LOOP-FINISH') exit in the do-body.</p>

  <p>Of course, the semantics of @('do$') is explicit in its definition.
  So you might want to execute @(':pe do$') in your ACL2 session and just
  read how @('do$') operates.</p>

  <p>We realize the above descriptions are pretty sketchy.  But in the coming
  discussions and proof problems we'll limit ourselves to @('DO') @('loop$')s
  without @('of-type')s or @('guards'), they'll all return single non-@(tsee
  stobj) values so the @(':values') option won't be needed, and you won't really
  need to use the @('finally') clause or any fancier bodies than we show in our
  examples.</p>

  <p>For more details about both the syntax and semantics of @('DO')
  @('loop$')s see @(see do-loop$).  <b>But beware!  That link takes you out of
  the @('loop$') primer!</b> To get back here either use your browser's
  &ldquo;back&rdquo; button or remember to return to @('lp-section-15')!</p>

  <p>Now go to @(see lp-section-16) (or return to the <see topic='@(url
  lp-section-0)'>Table of Contents</see>).</p>")
other
(defxdoc lp-section-16
  :parents (loop$-primer)
  :short "Proving Theorems about @('DO') @('Loop$')s"
  :long "<h3>LP16: Proving Theorems about @('DO') @('Loop$')s</h3>

  <p>Let's prove a theorem about a @('DO') @('loop$').  Specifically, let's
  prove</p>

  @({
  (defthm main
    (implies (natp n)
             (equal (loop$ with i = n
                           with ans = 0
                           do
                           (if (zp i)
                               (return ans)
                               (progn (setq ans (+ 1 ans))
                                      (setq i (- i 1)))))
                    n)))
  })

  <p>A few words of warning are appropriate.</p>

  <ul>

  <li>The Method (see @(see the-method)) is a good way to proceed:  try to
  prove the theorem expecting it to fail and look at the checkpoints.</li>

  <li>Unsurprisingly, the theorem above has to be <i>generalized</i> before it
  can be proved.  But it can feel strange to generalize a @('loop$').</li>

  <li>If we prove a lemma that rewrites a @('loop$') expression we have to
  remember that before rewrite rules are applied the interior terms are
  rewritten.  In particular, ACL2 can rewrite the bodies of the @('lambda')
  objects.  The most common changes are that non-recursive functions are
  generally expanded (depending on the theory in use) and @('IF')s
  are normalized.  That means we need to normalize the bodies of any @('loop$')
  we use in a lemma if we expect that lemma to match a term being rewritten!
  This observation is relevant here because @(tsee zp) is non-recursively
  defined and so will expand when the body of the @('loop$') above is
  rewritten.</li>

  <li>ACL2 does not display @('do$') terms as @('DO') @('loop$')s.  So get
  used to reading @('do$') terms and thinking of @('loop$') statements!
  (We may fix this someday but at the moment we find it advantageous to really
  see the terms the prover is dealing with!)</li>

  </ul>

  <p><b>A Tedious Recipe for Proving Theorems about @('DO') @('Loop$')s</b></p>

  <p>When you first start proving theorems about @('DO') @('loop$')s it might
  be helpful to follow the tedious recipe below.  It will familiarize you with
  the semantics of @('DO') @('loop$')s and teach you certain techniques that
  are easy applications of lessons you've already internalized as an
  experienced ACL2 user, albeit one unfamiliar with @('loop$').  But after a
  little experience you'll find it straightforward to skip some steps!</p>

  <ul>
  <li>Use The Method to find the normal form of the @('loop$').</li>

  <li>Define a recursive function that computes the value of the @('loop$')
  using the same algorithm as the @('loop$'). This function can serve two
  purposes.  First, it can be an intermediate stop on the way to proving that
  the @('loop$') satisfies your specification.  We'll make this clear in the
  next point.  Second, it can suggest an induction scheme that is probably
  useful.  We'll return to this point at the end of our recipe for proving
  things about @('DO') @('loop$')s.</li>

  <li>Prove that the @('loop$') computes the same value as the function.  We
  frequently refer to this as &ldquo;lemma 1&rdquo; in the recipe.  Generally
  you will have to generalize the @('loop$') to prove it by the induction
  suggested by the function.  And you will have to write the normal form of the
  @('loop$') body instead of the &ldquo;pretty&rdquo; form used in the main
  theorem so this lemma can be used to hit the rewritten @('loop$') in the
  proof of the main theorem later.</li>

  <li>Prove that the function satisfies the specification.  We
  frequently refer to this as &ldquo;lemma 2&rdquo;.</li>

  <li>Prove that the @('loop$') satisfies the specification by chaining
  together the two lemmas.</li>

  </ul>

  <p>Of course, as with all &ldquo;recipes&rdquo;, sometimes you have to adjust
  depending on the ingredients at hand.  Sometimes you can just write the body of
  the @('loop$') in normal form to begin with.   Sometimes you do not have to define a
  special function because the @('loop$') itself or a function already in the
  conjecture suggests an appropriate induction.  Sometimes you may find it
  easier to copy the @('do$') form revealed by The Method into your statement
  of lemma 1 and generalize that form, rather than try to express lemma 1 as a
  @('loop$').  You may also be content to skip the &ldquo;intermediate
  stop&rdquo; of lemma 1 altogether and prove that the @('loop$') satisfies a
  generalized specification, sometimes providing an @(':induct') hint instead
  of inserting the special function into the lemma.  Sometimes you do not have
  to generalize.  Sometimes instead of proving lemma 1 and lemma 2 you can just
  prove the main goal directly.  As an experienced ACL2 user you will recognize
  when you can skip steps in this recipe.  We spell the recipe out rigidly here
  just to give you one promising way to proceed.</p>

  <p>We're going to prove the theorem</p>

  @({
  (defthm main
    (implies (natp n)
             (equal (loop$ with i = n
                           with ans = 0
                           do
                           (if (zp i)
                               (return ans)
                               (progn (setq ans (+ 1 ans))
                                      (setq i (- i 1)))))
                    n)))
  })

  <p>both ways, first by following the tedious recipe, and then the way a user
  familiar with @('DO') @('loop$') proofs might do it.</p>

  <p>So here goes!  Following the recipe to prove @('main') above, we first try
  The Method.  The prover tries an induction suggested by the @('DO')
  @('loop$'), namely induction on @('N') by @('-1'), but without instantiating
  @('ANS') because the initial value of @('ANS') is the constant @('0').  We
  know this proof will fail and it does.  The pre-induction checkpoint is shown
  below.</p>

  @({
  *** Key checkpoint at the top level: ***

  Goal''
  (IMPLIES
   (AND (INTEGERP N) (<= 0 N))
   (EQUAL
    (DO$
       (LAMBDA$ (ALIST)
                (ACL2-COUNT (CDR (ASSOC-EQ-SAFE 'I ALIST))))
       (CONS (CONS 'I N) '((ANS . 0)))
       (LAMBDA$
            (ALIST)
            (IF (INTEGERP (CDR (ASSOC-EQ-SAFE 'I ALIST)))
                (IF (< 0 (CDR (ASSOC-EQ-SAFE 'I ALIST)))
                    (LIST NIL NIL
                          (LIST (CONS 'I
                                      (+ -1 (CDR (ASSOC-EQ-SAFE 'I ALIST))))
                                (CONS 'ANS
                                      (+ 1 (CDR (ASSOC-EQ-SAFE 'ANS ALIST))))))
                    (LIST :RETURN (CDR (ASSOC-EQ-SAFE 'ANS ALIST))
                          (LIST (CONS 'I (CDR (ASSOC-EQ-SAFE 'I ALIST)))
                                (CONS 'ANS
                                      (CDR (ASSOC-EQ-SAFE 'ANS ALIST))))))
                (LIST :RETURN (CDR (ASSOC-EQ-SAFE 'ANS ALIST))
                      (LIST (CONS 'I (CDR (ASSOC-EQ-SAFE 'I ALIST)))
                            (CONS 'ANS
                                  (CDR (ASSOC-EQ-SAFE 'ANS ALIST)))))))
       (LAMBDA$ (ALIST)
                (LIST NIL NIL
                      (LIST (CONS 'I (CDR (ASSOC-EQ-SAFE 'I ALIST)))
                            (CONS 'ANS
                                  (CDR (ASSOC-EQ-SAFE 'ANS ALIST))))))
       '(NIL) NIL)
    N))
  })

  <p>Look carefully at the @('do-body') @('lambda'), the second @('lambda')
  object in the @('do$').  The @('(ZP I)') in our original @('DO') @('loop$')
  has opened up, introducing @('(INTEGERP i)') and @('(< 0 i)') and @('IF')
  normalization -- except instead of seeing the simple variable @('I') we see
  its current value in the @('ALIST') being computed on each iteration.</p>

  <p><b>This is valuable information! It tells us what the rewritten body of
  the @('loop$') looks like in the theory in which our proof is being
  conducted.  If we prove a @(':rewrite') rule expecting it to fire during the
  proof of our @('main') theorem, its body must match that shown above!</b></p>

  <p>Now we define the recursive function that is supposed to be operationally
  equivalent to the @('loop$').  This will suggest the induction.</p>

  @({
  (defun copy-nat-ac (i ans)
    (if (zp i)
        ans
        (copy-nat-ac (- i 1)
                     (+ 1 ans))))
  })

  <p>Next comes the hard part.  We state the lemma that equates the @('loop$')
  to the function, but we have to generalize it so it can be proved by induction
  and we have to use the normal form of the body.  We could state the lemma
  in terms of @('DO$') of course, but with a little practice you can usually
  &ldquo;reverse engineer&rdquo; the desired lemma into a @('loop$').  So here
  is the so-called &ldquo;lemma 1&rdquo;.</p>

  @({
  (defthm lemma1
    (implies (and (natp n)
                  (natp ans0))
             (equal (loop$ with i = n
                           with ans = ans0
                           do
                           (if (integerp i)
                               (if (< 0 i)
                                   (progn (setq ans (+ 1 ans))
                                          (setq i (- i 1)))
                                   (return ans))
                               (return ans)))
                    (copy-nat-ac n ans0))))
  })

  <p>Note that we generalized the initial value of @('ans') in the @('loop$')
  from @('0') to @('ans0') and used @('ans0') as the accumulator in
  @('(copy-nat-ac n ans0)').</p>

  <p>By the way, we could have written @('lemma1') in terms of the @('DO$')
  term shown in the checkpoint, rather than as a @('loop$').  But we have to
  generalize that @('0') whether we use a @('loop$') or the @('DO$') term.
  The generalized @('DO$') form of @('lemma1') is</p>

  @({
  (defthm lemma1
    (implies
     (and (natp n)
          (natp ans0))
     (equal
      (DO$
       (LAMBDA$ (ALIST)
                (ACL2-COUNT (CDR (ASSOC-EQ-SAFE 'I ALIST))))
       (CONS (CONS 'I N)
             (cons (cons 'ans ans0)
                   nil)) ; note generalization of 0!
       (LAMBDA$
        (ALIST)
        (IF (INTEGERP (CDR (ASSOC-EQ-SAFE 'I ALIST)))
            (IF (< 0 (CDR (ASSOC-EQ-SAFE 'I ALIST)))
                (LIST NIL NIL
                      (LIST (CONS 'I
                                  (+ -1 (CDR (ASSOC-EQ-SAFE 'I ALIST))))
                            (CONS 'ANS
                                  (+ 1 (CDR (ASSOC-EQ-SAFE 'ANS ALIST))))))
                (LIST :RETURN (CDR (ASSOC-EQ-SAFE 'ANS ALIST))
                      (LIST (CONS 'I (CDR (ASSOC-EQ-SAFE 'I ALIST)))
                            (CONS 'ANS
                                  (CDR (ASSOC-EQ-SAFE 'ANS ALIST))))))
            (LIST :RETURN (CDR (ASSOC-EQ-SAFE 'ANS ALIST))
                  (LIST (CONS 'I (CDR (ASSOC-EQ-SAFE 'I ALIST)))
                        (CONS 'ANS
                              (CDR (ASSOC-EQ-SAFE 'ANS ALIST)))))))
       (LAMBDA$ (ALIST)
                (LIST NIL NIL
                      (LIST (CONS 'I (CDR (ASSOC-EQ-SAFE 'I ALIST)))
                            (CONS 'ANS
                                  (CDR (ASSOC-EQ-SAFE 'ANS ALIST))))))
       '(NIL) NIL)
      (copy-nat-ac n ans0)))).
  })

  <p>The UPPERCASE part above was just copied from the checkpoint and then the
  pair in the initial alist binding @('ANS'), which was @(''(ANS . 0)'), was
  replaced by @('(cons (cons 'ans ans0) nil)').  So while it looks messy, it's
  not hard to enter.  Furthermore, it saves us from having to figure out the
  normal form &mdash; it's already in the checkpoint.  The @('DO$') term in
  this version of @('lemma1') is just the formal translation of the generalized
  @('DO') @('loop$') we wrote in the earlier version of @('lemma1').</p>

  <p>Next we prove &ldquo;lemma 2&rdquo; equating the recursive function with
  the (generalized) specification.  This theorem does not involve @('loop$')
  and its proof should be utterly familiar to you.</p>

  @({
  (defthm lemma2
    (implies (and (natp n)
                  (natp ans0))
             (equal (copy-nat-ac n ans0)
                    (+ n ans0))))
  })

  <p>Finally, we prove our main theorem.</p>

  @({
  (defthm main
    (implies (natp n)
             (equal (loop$ with i = n
                           with ans = 0
                           do
                           (if (zp i)
                               (return ans)
                               (progn (setq ans (+ 1 ans))
                                      (setq i (- i 1)))))
                    n)))
  })

  <p>The proof rewrites the &ldquo;pretty&rdquo; @('do-body') @('lambda') into
  the normal form, @('lemma1') rewrites the new form of the @('loop$') after
  instantiating @('ans0') to @('0'), to @('(copy-nat-ac n 0)'), then
  @('lemma2') hits that to @('(+ n 0)'), and arithmetic does the rest.</p>

  <p>As we noted, our recipe is overly rigid.  Here is another sequence of
  events that proves @('main').  The experienced user realizes that the
  generalized @('DO') @('loop$') will in fact suggest the appropriate induction
  to ACL2.  So no special function is introduced.  Furthermore, the user
  &mdash; who has proved several theorems about @('loop$')s involving @('IF')
  and @('ZP') will know how to write the normal form.  That user would just do
  this.</p>

  @({
  (defthm lemma
    (implies
     (and (natp n) (natp ans0))
     (equal (loop$ with i = n
                   with ans = ans0
                   do
                   (if (integerp i)
                       (if (< 0 i)
                           (progn (setq ans (+ 1 ans))
                                  (setq i (- i 1)))
                           (return ans))
                       (return ans)))
            (+ n ans0))))

  (defthm main
    (implies (natp n)
             (equal (loop$ with i = n
                           with ans = 0
                           do
                           (if (zp i)
                               (return ans)
                           (progn (setq ans (+ 1 ans))
                                  (setq i (- i 1)))))
                    n)))
  })

  <p>For more details about rewriting @('lambda') objects you can leave the
  @('loop$') primer and read @(see rewrite-lambda-object) and @(see
  rewriting-versus-cleaning-up-lambda-objects).  But remember to come
  <b>back</b> here to @('lp-section-16')!</p>

  <p>Now go to @(see lp-section-17) (or return to the <see topic='@(url
  lp-section-0)'>Table of Contents</see>).</p>")
other
(defxdoc lp-section-17
  :parents (loop$-primer)
  :short "Challenge Proof Problems for @('DO') @('Loop$')s"
  :long "<h3>LP17: Challenge Proof Problems for @('DO') @('Loop$')s</h3>

  <p>In the following problems please write @('DO') @('loop$')s even though some
  of the problems can be solved with @('FOR') @('loop$')s.</p>

  <p>Our answers to the problems in this section are in @(see community-books)
  file @('demos/loop-primer/lp17.lisp').</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP17-1:</b> Write a @('DO') @('loop$') that reverses the list @('lst').
  For example, if @('lst') is @('(A B C)') the result should be @('(C B A)').
  Prove that your @('DO') @('loop$') is equal to @('(rev lst)'), where</p>

  @({
  (defun rev (x)
    (if (endp x)
        nil
        (append (rev (cdr x)) (list (car x)))))
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP17-2:</b> Write a @('DO') @('loop$') that computes @('(member e
  lst)') and prove it correct.</p>

  <p><b>Hint:</b> Sometimes the main theorem suggests the right induction on
  its own.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP17-3:</b> Prove the following:</p>

  @({
  (defthm lp17-3-main
    (equal (loop$ with x = lst
                  with ans = 0
                  do
                   (cond ((endp x) (return ans))
                         (t (progn (setq ans (+ 1 ans))
                                   (setq x (cdr x))))))
           (len lst)))
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP17-4:</b> Write a @('DO') @('loop$') that computes @('(nth n lst)'),
  when @('n') is a natural number.  Prove it correct.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP17-5:</b>  Prove the following.</p>

  @({
  (defthm lp17-5-main
    (implies (true-listp lst)
             (equal (loop$ with x = lst
                           with ans = nil
                           do
                           (cond
                            ((endp x) (return ans))
                            (t (progn (setq ans (append ans (list (car x))))
                                      (setq x (cdr x))))))
                    lst)))
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP17-6:</b>  Prove the following.</p>

  @({
  (defthm lp17-6-main
    (implies (and (natp m)
                  (natp n))
             (equal (loop$ with i = m
                           with j = n
                           do
                           (if (zp i)
                               (return j)
                               (progn (setq i (- i 1))
                                      (setq j (+ j 1)))))
                    (+ m n))))
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP17-7:</b> Write a @('DO') @('loop$') that computes @('(fact n)'), for
  natural number @('n'), where</p>

  @({
  (defun fact (n)
    (if (zp n)
        1
        (* n (fact (- n 1)))))
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP17-8:</b> Write a @('DO') @('loop$') that scans a list of numbers,
  @('lst'), once and returns the sum of the elements and the sum of the
  squares (with @('sq') as defined below) of the elements of @('lst') as a cons
  pair.  E.g., given @('(1 2 3 4 5)') return @('(cons (+ 1 2 3 4 5) (+ (sq
  1) (sq 2) (sq 3) (sq 4) (sq 5)))') = @('(15 . 55)').</p>

  <p>Prove that your do loop$ is equal to</p>

  @({
  (cons (loop$ for e in lst sum e)
        (loop$ for e in lst sum (sq e)))
  })

  <p>Use the following definition of @('sq').</p>

  @({
  (defun sq (x) (* x x))
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP17-9:</b> Define @('(partition-symbols lst)') with a @('DO')
  @('loop$') that partitions @('lst') into two lists, one containing all the
  symbols in @('lst') and the other containing all the non-symbols.  Return the
  cons of the two partitions and prove @('partition-symbols') correct.</p>

  <p>Hint: Since you are likely to collect the elements in reverse order, a
  suitable specification for these purposes is that @('partition-symbols')
  is equal to</p>

  @({
  (cons (rev (loop$ for e in lst when (symbolp e) collect e))
        (rev (loop$ for e in lst when (not (symbolp e)) collect e)))
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP17-10:</b> Write a @('DO') @('loop$') that returns the list of
  naturals from @('n') down to @('0'), where @('n') is a natural.  For example,
  if @('n') is @('10') the answer is @('(10 9 8 7 6 5 4 3 2 1 0)').  Prove that
  when @('n') is a natural, your @('DO') @('loop$') returns the same thing as
  @('(loop$ for i from 0 to n collect (- n i))').</p>

  <p> Hints: Remember that in order for your &ldquo;lemma1&rdquo; to be applied
  in the proof of your main theorem it must match the rewritten lambda objects
  of the main theorem.  We've focused on matching the @('do-body') @('lambda').
  But it must also match the measure @('lambda').  So when you formulate your
  &ldquo;lemma1&rdquo;, pay attention to how your measure term normalizes under
  rewrite.  And by the way, if you use non-recursive functions in a term and
  you don't want them opened up when the lambda objects are rewritten in the
  main theorem, try disabling them.  (Some non-recursive functions cannot be
  disabled.  But another workaround is to define the whole measure as a
  function and disable it when appropriate.)</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p><b>LP17-11:</b> Define @('(all-pairs-do-loop$ imax jmax)') to compute the same
  @('(all-pairs imax jmax)') as was defined in section 11 (and below).
  But use @('DO') @('loop$s') instead of @('FOR') @('loop$')s in your
  definition of @('all-pairs-do-loop$').  Below we comment on what you
  should prove.</p>

  <p>The definition of @('all-pairs') was as follows.</p>

  @({
  (defun make-pair (i j)
    (declare (xargs :guard t))
    (cons i j))

  (defwarrant make-pair)

  (defun all-pairs-helper2 (i j jmax)
    (declare (xargs :measure (nfix (- (+ (nfix jmax) 1) (nfix j)))
                    :guard (and (natp i) (natp j) (natp jmax))))
    (let ((j (nfix j))
          (jmax (nfix jmax)))
      (cond
       ((> j jmax) nil)
       (t (cons (make-pair i j)
                (all-pairs-helper2 i (+ 1 j) jmax))))))

  (defun all-pairs-helper1 (i imax jmax)
    (declare (xargs :measure (nfix (- (+ (nfix imax) 1) (nfix i)))
                    :guard (and (natp i) (natp imax) (natp jmax))))
    (let ((i (nfix i))
          (imax (nfix imax)))
      (cond
       ((> i imax) nil)
       (t (append (all-pairs-helper2 i 1 jmax)
                  (all-pairs-helper1 (+ 1 i) imax jmax))))))

  (defun all-pairs (imax jmax)
    (declare (xargs :guard (and (natp imax) (natp jmax))))
    (all-pairs-helper1 1 imax jmax))
  })

  <p>Hints: In following our advice on proving do loop$s you will define
  functions that compute the same things as your @('DO') @('loop$')s.  In our
  solution we called these two functions @('apdh1') and @('apdh2'), where
  &ldquo;@('apdh')&rdquo; stands for @ldquo;@('all-pairs-do-helper')&rdquo;.
  You will prove two &ldquo;@('lemma1')&rdquo; theorems, one for each @('loop$').
  The second of those theorems will establish allow you to prove that your
  @('all-pairs-do-loop$') is @('apdh1').</p>

  <p>The next step in our recipe is to prove that the @('apdh1') is
  @('all-pairs') as above.  This will not involve @('loop$')s of any sort.
  It's just a normal proof about the relation between some recursively defined
  functions.  But we found this step surprisingly challenging!</p>

  <p>Since that second step does not involve @('loop$')s, you may consider your
  answer correct if you just prove the two &ldquo;@('lemma1')&rdquo; theorems!
  But if you want a non-@('loop$') challenge, finish the proof all the way to
  @('all-pairs').</p>

  <p>Now go to @(see lp-section-18) (or return to the <see topic='@(url
  lp-section-0)'>Table of Contents</see>).</p>")
other
(defxdoc lp-section-18
  :parents (loop$-primer)
  :short "Conclusion"
  :long "<h3>LP18: Conclusion</h3>

  <p>Here are two pieces of advice.</p>

  <p>First, if you can think of a good name for the concept implemented by a
  @('loop$') statement, use @('defun') to define that name.  This is especially
  the case if you intend to reason about that @('loop$') statement or to write
  more than one instance of it.</p>

  <p>For example, rather than write instances of</p>

  @({
  (loop$ for a in x as b in y sum (* a b))
  })

  <p>it is better to define @('(dot-product x y)') with that @('loop$') as its body
  and then write calls of @('dot-product').</p>

  <p>Basically, names are good as long as you can remember them.  They give you
  a place to hang lemmas and the lemmas match without having to think about
  rewriting lambdas, local variables, etc.  Not all @('loop$')s compute concepts
  with obvious, memorable names, but just because you can write
  &ldquo;anonymous&rdquo; iterations doesn't mean you should!</p>

  <p>Second, remember when you create a lemma intended to rewrite a @('loop$')
  statement you should normalize the body under your intended rewrite theory.
  As an experienced ACL2 user you would never write a lemma that tried to
  rewrite an @('endp') or @('nfix') or @('zp') term.  The lemma will never
  &ldquo;see&rdquo; such terms because the rewriter will have opened them up.
  You should apply that same kind of thinking when you write lemmas intended to
  rewrite @('loop$')s.</p>

  <p>That's it.  We can't think of anything else to say!  We urge you to resort
  to the ACL2 user's manual for further information.</p>

  <p>Some relevant topics are</p>

  <ul>
  <li>@(tsee loop$)</li>
  <li>@(see for-loop$)</li>
  <li>@(see do-loop$)</li>
  <li>@(tsee lambda$)</li>
  <li>@(see rewrite-lambda-object)</li>
  <li>@(see stating-and-proving-lemmas-about-loop$s)</li>
  </ul>

  <p>The End of the @('Loop$') Primer. (Return to the <see topic='@(url
  lp-section-0)'>Table of Contents</see>).</p>")
other
(defxdoc lp-background-review-2
  :parents (lp-section-1)
  :short "Review of @(tsee apply$) and related concepts"
  :long "<p>Below are some questions designed to review basic knowledge of
  @(tsee apply$) and related concepts used in the semantics of @('loop$').  For
  our answers see @(see lp-background-review-2-answers).</p>

  <p>But our answers are sometimes quite long and elaborate &mdash; more like
  little lectures on the subject than just answers.  So don't expect to
  reproduce our answers.  It's up to you to decide if you know this stuff.  As
  you use @('loop$'), ACL2 will print warnings and error messages about
  functions not having badges or warrants or expressions not being tame.  We
  don't want your reaction to be &ldquo;Ack! What's that all about?&rdquo; We
  want it to be at least &ldquo;Oh yes, I remember now.&rdquo; We recommend
  that after you've read and answered the questions, you read our answers even
  if you're pretty confident in your answers.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>Consider these events, executed as the first three events in new ACL2
  sessions.</p>

  @({
  (include-book "projects/apply/top" :dir :system)

  (defun sq (x)
    (declare (xargs :guard (natp x)))
    (* x x))

  (defun ghi (fn lst)
    (declare (xargs :guard (and (apply$-guard fn '(nil))
                                (true-listp lst))))
    (cond
      ((endp lst) nil)
      (t (cons (apply$ fn (list (car lst)))
               (ghi fn (cdr lst))))))
  })

  <p>The three events are executed without error and @('sq') and @('ghi') are
  admitted in @(':logic') mode.  By the way, we're naming certain functions in
  these reviews with consecutive letters of the alphabet, e.g., @('abc'),
  @('def'), @('ghi'), @('jkl'), @('mno'), etc.  These names are not mnemonic or
  acronyms.  Don't read anything into the names!  Note that unlike the review
  of elementary ACL2 features (see @(tsee lp-background-review-1)),
  here we define @('(sq x)') with a guard of @('(natp x)').  Both @('sq') and
  @('ghi') are guard verified upon admission.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>1: What is the value of @('(ghi 'sq '(1 2 3))')?  Hint: This is a trick
  question!</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>2: How do you assign a badge and warrant to @('sq')?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>3: What is the name of the &ldquo;warrant function for @('sq')?&rdquo;  What does
  @('(warrant sq)') abbreviate?  What does @('(warrant sq)') imply about
  @('badge') and @('apply$')?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>4: Can @('ghi') be warranted?  If so, what command do you type?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>5: What is the name of the warrant function for @('ghi')?  Explain what
  the warrant for @('ghi') tells us.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>6: The following definition is admissible.  Can it be warranted?</p>

  @({
  (defun mno (x y z)
    (if (endp x)
        z
        (apply$ y
                (list (car x)
                      (mno (cdr x) y z)))))
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>7: Is @('(equal (mno x 'cons y) (append x y))') a theorem?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>8: The following @('defun') is admissible but cannot be warranted.
  Why?</p>

  @({
  (defun xyz (x) (apply$ x (list x)))
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>9: Recall @('ghi') as defined at the beginning of this review.  Assume
  @('sq') has been warranted.  What is the value of @('(ghi 'sq '(1 2
  3))')?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>10: Is @('(nat-listp (ghi 'sq lst))') a theorem?  If not, what theorem
  does this suggest?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>11: What is the value of the term below?</p>

  @({
  (ghi (lambda$ (e) (ghi 'sq e))
       '((1 2 3)
         (4 5 6)
         (7 8 9)))
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>12: Suppose you want to define @('jkl') to be something like what's shown
  below and you want the guards verified.</p>

  @({
  (defun jkl (lst)
    (declare (xargs :guard ...))
    (ghi (lambda$ (e) (ghi 'sq e)) lst)))
  })

  <p>Notice that the body of @('jkl') is the doubly nested @('ghi') term just
  tested, except now instead of applying it to a constant list we're applying
  it to the argument of @('jkl').</p>

  <p>What is the appropriate @(':')@(tsee guard) and do you have to make other
  modifications to the suggested @('defun') of @('jkl')?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>13: Can @('jkl') be warranted?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>14: Is this a theorem?  If not, what theorem does it suggest?</p>

  @({
  (implies (nat-listp-listp lst)
           (nat-listp-listp (jkl lst)))
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>See @(see lp-background-review-2-answers) for our answers.  If
  your answers basically agree with ours we think you're ready to learn about
  @('loop$'), so go back to the @(see loop$-primer).  Otherwise, we strongly
  recommend that you read @(see introduction-to-apply$) and then @(tsee apply$)
  before reading about @('loop$').</p>

  <p>(Return to the <see topic='@(url lp-section-0)'>Table of
  Contents</see>.)</p>")
other
(defxdoc lp-background-review-2-answers
  :parents (lp-section-1)
  :short "Answers to the review of @(tsee apply$) and related concepts"
  :long "<p>Below are our answers to the Review of @(tsee apply$) and related
  concepts.  If your answers basically agree with ours, we think you're ready
  to follow the discussion in @(tsee loop$-primer).  If not, we recommend that
  you read @(see introduction-to-apply$) and then @(tsee apply$) before reading
  about @('loop$').</p>

  <p>But our answers are sometimes quite long and elaborate &mdash; more like
  little lectures on the subject than just answers.  So don't expect to
  reproduce our answers.  It's up to you to decide if you know this stuff.  As
  you use @('loop$'), ACL2 will print warnings and error messages about
  functions not having badges or warrants or expression not being tame.  We
  don't want your reaction to be &ldquo;Ack! What's that all about?&rdquo;  We want it to
  be at least &ldquo;Oh yes, I remember now.&rdquo;  So we recommend that you read these
  little mini-lectures in full.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>Consider these events, executed as the first three events in new ACL2
  sessions.</p>

  @({
  (include-book "projects/apply/top" :dir :system)

  (defun sq (x)
    (declare (xargs :guard (natp x)))
    (* x x))

  (defun ghi (fn lst)
    (declare (xargs :guard (and (apply$-guard fn '(nil))
                                (true-listp lst))))
    (cond
      ((endp lst) nil)
      (t (cons (apply$ fn (list (car lst)))
               (ghi fn (cdr lst))))))
  })

  <p>The three events are executed without error and @('sq') and @('ghi') are
  admitted in @(':logic') mode.  By the way, we're naming certain functions in
  these reviews with consecutive letters of the alphabet, e.g., @('abc'),
  @('def'), @('ghi'), @('jkl'), @('mno'), etc.  These names are not mnemonic or
  acronyms.  Don't read anything into the names!  Note that unlike the review
  of elementary ACL2 features (see @(tsee lp-background-review-1)),
  here we define @('(sq x)') with a guard of @('(natp x)').  Both @('sq') and
  @('ghi') are guard verified upon admission.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>1: What is the value of @('(ghi 'sq '(1 2 3))')?  Hint: This is a trick
  question!</p>

  <p>Answer: Note that @('ghi') is a @(see scion) of @('apply$').  It calls
  @('apply$'), passing in the first argument of @('ghi') as the &ldquo;function&rdquo; to
  @('apply$').  The evaluation of the above term fails with an error message
  because @('sq') is a user-defined @(':')@(tsee logic) mode function but has
  not been @(see warrant)ed (see @(tsee defwarrant)).  @(':Logic') mode
  functions must be warranted to be applied (with @('apply$')) at the top-level
  of the ACL2 read-eval-print loop.  Furthermore, if you ever try to prove a
  theorem whose proof requires expansion of the applications (with @('apply$'))
  of such functions, their warrants must be provided as hypotheses.  We'll get
  to that later.</p>

  <p>By the way, @(':')@(tsee program) mode functions must be @(tsee
  badge)d (see @(tsee defbadge)) to be applied at the top-level, but they need
  not be warranted (because @(':program') mode functions cannot be warranted or
  used meaningfully in conjectures to be proved).  See @(see
  guarantees-of-the-top-level-loop) for a discussion of the badge and warrant
  restrictions enforced by top-level evaluation.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>2: How do you assign a badge and warrant to @('sq')?</p>

  <p>Answer: @('(defwarrant sq)').</p>

  <p>@(tsee Defwarrant) assigns both a badge and a warrant to its argument, which
  must be a @(':logic') mode function satisfying certain restrictions on how it
  uses its arguments and how the termination of the function is justified.  If the
  function cannot be badged or cannot be warranted, an error is printed.</p>

  <p>@(tsee Defbadge) just assigns a badge and can work on @(':program') or
  @(':logic') mode functions.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>3: What is the name of the &ldquo;warrant function for @('sq')?&rdquo;  What does
  @('(warrant sq)') abbreviate?  What does @('(warrant sq)') imply about
  @('badge') and @('apply$')?</p>

  <p>Answer: The warrant function for @('sq') is named @('apply$-warrant-sq'),
  which is a 0-ary predicate.  @('(Warrant sq)') is just an abbreviation for a
  call of @('apply$-warrant-sq') and if more than one function symbol appears
  after the symbol @('warrant') then it expands to the conjunction of each of
  their predicates.  We'll show an example later.</p>

  <p>@('Apply$-warrant-sq') is introduced as a constrained function using
  @(tsee defun-sk).  Here is the event in question, but the details here are
  not critical to the present discussion.</p>

  @({
  (defun-sk apply$-warrant-sq ()
    (forall (args)
      (and
       (equal (badge-userfn 'sq) '(apply$-badge 1 1 . t))
       (equal (apply$-userfn 'sq args)
              (sq (car args)))))
    :constrain t)
  })

  <p>What is critical is the role that @('(apply$-warrant-sq)') plays in the
  following theorem, which is proved as a @(':')@(tsee rewrite) rule by
  @('(defwarrant sq)').</p>

  @({
  (defthm apply$-sq
    (implies (force (apply$-warrant-sq))
             (and (equal (badge 'sq)
                         '(apply$-badge 1 1 . t))
                  (equal (apply$ 'sq args)
                         (sq (car args))))))
  })

  <p>which allows the prover to reduce @('(badge 'sq)') to @('(apply$-badge 1 1
  . t)') and to reduce any instance of @('(apply$ 'sq args)') to @('(sq (car
  args))').</p>

  <p>The @(tsee badge) of @('sq') tells the prover that @('sq') is a function
  of one argument that returns one result.  The &ldquo;@(' . t')&rdquo; means &ldquo;all the
  arguments are ordinary objects,&rdquo; i.e., never treated like &ldquo;functions.&rdquo;</p>

  <p>The second part of the rule above will reduce the typical application of
  @('sq'), e.g., @('(apply$ 'sq (list e))'), to @('(sq e)').</p>

  <p>Finally, note that name of the rule is @('apply$-sq'), both the @('badge')
  and @('apply$') reductions are conditional on the warrant hypothesis for
  @('sq'), and that the warrant hypothesis is @(tsee force)d.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>4: Can @('ghi') be warranted?  If so, what command do you type?</p>

  <p>Answer: Yes!  Just type @('(defwarrant ghi)').</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>5: What is the name of the warrant function for @('ghi')?  Explain what
  the warrant for @('ghi') tells us.</p>

  <p>Answer: The warrant function for @('ghi') is named
  @('apply$-warrant-ghi').  @('(warrant ghi)') abbreviates
  @('(apply$-warrant-ghi)'), and, by the way, @('(warrant sq ghi ...)') expands
  to</p>

  @({
  (and (apply$-warrant-sq)
       (apply$-warrant-ghi)
       ...).
  })

  <p>The rule @('apply$-ghi') is proved by @('defwarrant').</p>

  @({
  (defthm apply$-ghi
    (and (implies (force (apply$-warrant-ghi))
  		(equal (badge 'ghi)
  		       '(apply$-badge 2 1 :fn nil)))
         (implies (and (force (apply$-warrant-ghi))
  		     (tamep-functionp (car args)))
  		(equal (apply$ 'ghi args)
  		       (ghi (car args) (car (cdr args)))))))
  })

  <p>Notice that @('apply$-ghi') is really two @(':rewrite') rules, both
  conditioned on the forced warrant for @('ghi').</p>

  <p>The first rule tells us what the @(tsee badge) of @('ghi') is.  In
  particular we see that the first argument of @('ghi') has &ldquo;@(see ilk)&rdquo;
  @(':')@('fn'), which means that argument is treated as a function and can
  eventually be applied with @('apply$').  Arguments of ilk @(':fn') are never
  treated as ordinary objects.  The badge of @('ghi') also tells us the second
  argument has ilk @('nil'), which means it is an ordinary object (and is never
  treated as a function).  The details are in @(tsee defbadge).</p>

  <p>Note that the second conjunct of the @('apply$-ghi') rule above rewrites
  instances of @('(apply$ 'ghi args)') and would rewrite @('(apply$ 'ghi (list
  x y))') to @('(ghi x y)').  However, it can only be used if the first
  argument passed to @('ghi'), namely @('x') above, is a @(see tame) function.
  Ilks, warrants, and tameness are concepts that are critical to the soundness
  of ACL2's handling of @('apply$').  For details see @(tsee apply$).</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>6: The following definition is admissible.  Can it be warranted?</p>

  @({
  (defun mno (x y z)
    (if (endp x)
        z
        (apply$ y
                (list (car x)
                      (mno (cdr x) y z)))))
  })

  <p>Answer: Yes.  Its badge is determined to be @('(apply$-badge 3 1 nil :fn
  nil)').</p>

  <p>For example,</p>

  @({
  (mno '(1 2 3) 'cons '(4 5 6))
  =
  (cons 1 (mno '(2 3) 'cons '(4 5 6)))
  =
  (cons 1 (cons 2 (mno '(3) 'cons '(4 5 6))))
  =
  (cons 1 (cons 2 (cons 3 (mno 'nil 'cons '(4 5 6)))))
  =
  (cons 1 (cons 2 (cons 3 '(4 5 6))))
  =
  '(1 2 3 4 5 6)
  })

  <p>In fact, @('mno') is more often named &ldquo;@('foldr')&rdquo; in the functional
  programming literature.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>7: Is @('(equal (mno x 'cons y) (append x y))') a theorem?</p>

  <p>Answer: Yes!  You might think we need to add the warrant hypothesis for
  @('cons') since @('(apply$ 'cons ...)') must be expanded to do the proof.
  However, most ACL2 primitives, like @('cons'), are built into the definition
  of @('apply$') and warrants are not necessary for them.  In fact, the
  primitives don't have warrant functions.  E.g., @('(apply$ 'cons (list x
  y))') is @('(cons x y)'), unconditionally.  The complete list of @('apply$')
  primitives may be exhibited by evaluating</p>

  @({
  (append '(BADGE TAMEP TAMEP-FUNCTIONP SUITABLY-TAMEP-LISTP
                  APPLY$ EV$)
          (strip-cars *badge-prim-falist*)).
  })

  <p>However, <i>user-defined function symbols</i> need warrants in order to be
  applied (with @('apply$')).  But not all user-defined symbols can be
  warranted.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>8: The following @('defun') is admissible but cannot be warranted.
  Why?</p>

  @({
  (defun xyz (x) (apply$ x (list x)))
  })

  <p>Answer: It is impossible to classify the argument @('x').  Is it a
  function or is it an ordinary object?  It's used both ways.  @('(Defwarrant
  xyz)') fails.</p>

  <p>In order for @('apply$') to be able to handle a function symbol certain
  restrictions must hold.  These restrictions guarantee that there is a model
  that makes all warrants true.  Here's a way to think about it.  Imagine that
  @('apply$') is defined as a big case analysis that enumerates all the
  functions that @('apply$') can handle and calls them appropriately.  That big
  definition of @('apply$') has some measure that explains why it terminates
  &mdash; a fairly messy measure given that @('apply$') can all @('ghi') which
  calls @('apply$').  Now imagine you want to define a new function, e.g.,
  @('xyz'), and change the definition of that big @('apply$') to include all
  the old functions plus @('xyz').  You'll need to weave the measure of
  @('xyz') into the measure of the big @('apply$').  @('Defwarrant') enforces
  restrictions that tell us this is possible.  Of course, the restrictions are
  overly restrictive: to be perfect @('defwarrant') would have to solve the
  halting problem.</p>


  <p>While the failure of @('(defwarrant xyz)') prevents us from being able to
  use @('apply$') to apply @('xyz'), it is possible to evaluate some calls of
  @('xyz') and to prove theorems about them.</p>

  @({
  (thm
    (equal (xyz '(lambda (x) (len x))) 3)
  })

  <p>In the proof of the theorem above, @('xyz') applied the given @('lambda')
  object to itself and computed that its length is 3.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>9: Recall @('ghi') as defined at the beginning of this review.  Assume
  @('sq') has been warranted.  What is the value of @('(ghi 'sq '(1 2
  3))')?</p>

  <p>Answer: @('(1 4 9)').</p>

  <p>Recall that an earlier question established that @('ghi') can be warranted
  and one might think warranting @('ghi') is necessary for @('(ghi 'sq '(1 2
  3))') to be evaluated without error.  But that's untrue.  @('Ghi') is not
  being applied (with @('apply$')) here, so whether it has been warranted or
  not is irrelevant.  However, @('sq') is being applied.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>10: Is @('(nat-listp (ghi 'sq lst))') a theorem?  If not, what theorem
  does this suggest?</p>

  <p>Answer: No, it's not a theorem as written.  For example @('(ghi 'sq '(-1/2
  #c(0 1)))') has the value @('(1/4 -1)'), although to get that value computed
  by the top-level read-eval-print loop you have to turn off guard
  checking (see @(tsee set-guard-checking)).</p>

  <p>The following is a theorem.</p>

  @({
  (implies (and (warrant sq)
                (nat-listp lst))
           (nat-listp (ghi 'sq lst)))
  })

  <p>The @('warrant') hypothesis for @('sq') is necessary because to prove
  anything interesting about @('(apply$ 'sq ...)') we need the warrant for
  @('sq').  The @('nat-listp') hypothesis is necessary because otherwise
  @('sq') may not return a natural number.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>11: What is the value of the term below?</p>

  @({
  (ghi (lambda$ (e) (ghi 'sq e))
       '((1 2 3)
         (4 5 6)
         (7 8 9)))
  })

  <p>Answer: @('((1 4 9) (16 25 36) (49 64 81))').</p>

  <p>@(tsee Lambda$) is an interesting ACL2 feature.  It translates the body
  term and constructs a @('lambda') object suitable for @('apply$').</p>

  <p>The @('ghi') term above is also interesting.  It shows that the outer call
  of @('ghi') can successfully @('apply$') the @('lambda') object which itself
  calls @('ghi') on @('sq').</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>12: Suppose you want to define @('jkl') to be something like what's shown
  below and you want the guards verified.</p>

  @({
  (defun jkl (lst)
    (declare (xargs :guard ...))
    (ghi (lambda$ (e) (ghi 'sq e)) lst)))
  })

  <p>Notice that the body of @('jkl') is the doubly nested @('ghi') term just
  tested, except now instead of applying it to a constant list we're applying
  it to the argument of @('jkl').</p>

  <p>What is the appropriate @(':')@(tsee guard) and do you have to make other
  modifications to the suggested @('defun') of @('jkl')?</p>

  <p>Answer: First, we define a predicate that recognizes a list of
  @('nat-listp')s, i.e., a list of lists, where each element of each of the
  inner lists is a natural number.</p>

  @({
  (defun nat-list-listp (lst)
    (declare (xargs :guard (true-listp lst)))
    (if (endp lst)
        t
        (and (nat-listp (car lst))
             (nat-list-listp (cdr lst)))))
  })

  <p>We could warrant @('nat-list-listp') with @('(defwarrant
  nat-list-listp)') if we wanted to, but because it is only used in a guard
  below, a warrant is not necessary.  If we intend to apply it with @('apply$')
  we would need a warrant and we can always warrant it when needed.</p>

  <p>We can then define @('jkl') with the :@('guard') shown below.  The
  @('true-listp') conjunct of the guard below is necessary because
  @('nat-list-listp') has @('true-listp') as its guard.  But note that we also
  modified the @(tsee lambda$) expression to express the guard on its local
  variable @('e').</p>

  @({
  (defun jkl (lst)
    (declare (xargs :guard (and (true-listp lst)
  			      (nat-list-listp lst))))
    (ghi (lambda$ (e)
                  (declare (xargs :guard (nat-listp e)))
                  (ghi 'sq e))
         lst))
  })

  <p>@('Jkl') is guard verified upon admission.  Consider what that means.  In
  particular, every time @('sq') is called it is called on something satisfying
  the guard of @('sq').  The guard proof obligations generated for a nest of
  functions using @('apply$') can be quite messy.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>13: Can @('jkl') be warranted?</p>

  <p>Answer: Yes.  @('(defwarrant jkl)') succeeds.  A key observation is that
  the @('lambda$') expression in its definition is a @('tame') function (see
  @('tame')).  That is syntactically determined because the body of the
  @('lambda$') is @('(ghi 'sq e)'), @('ghi') requires a tame function as its
  first argument, and @('sq') is a tame function.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>14: Is this a theorem?  If not, what theorem does it suggest?</p>

  @({
  (implies (nat-list-listp lst)
           (nat-list-listp (jkl lst)))
  })

  <p>Answer: It is not quite a theorem as written.  We need to add warrant
  hypotheses for the functions being applied with @('apply$').  Note that
  @('jkl') is not being applied, so we don't need its warrant.  The outer
  @('ghi') in the definition of @('jkl') is also not being applied.  But the
  @(tsee lambda$) expression passed as an argument to the outer @('ghi') is
  being applied by the outer @('ghi'), and to evaluate the body of that
  @('lambda') object we @('apply$') @('ghi'), so we need the warrant for
  @('ghi') there.  Furthermore, that inner @('ghi') will apply @('sq').  So we
  need the warrant for that.</p>

  <p>Thus, the following is indeed a theorem.</p>

  @({
  (implies (and (warrant ghi sq)
                (nat-list-listp lst))
           (nat-list-listp (jkl lst)))
  })

  <p>For some heuristic advice on how to figure out the necessary warrants, see
  the section &ldquo;Determining the Necessary Warrants&rdquo; in see @(tsee
  warrant).</p>

  <p>However, if you omit the warrant hypotheses ACL2 will often &ldquo;remind&rdquo; you
  at the end of failed proof attempts by exhibiting checkpoints derived from
  forcing the warrants when @('apply$') rules are applied.  If the warrants are
  omitted in this particular theorem checkpoints require proving both
  @('(apply$-warrant-sq)') and @('(apply$-warrant-ghi)').</p>

  <p>Finally, one might worry that it is impossible for all the listed warrants
  to be true at once, so perhaps listing a bunch of warrants might make your
  theorems vacuously valid.  But @('defwarrant') ensures that there is a model
  of the ACL2 logic in which all warrants are valid.  Thus, adding warrant
  hypotheses in no way makes your theorems less meaningful.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>If your answers basically agree with ours you should proceed on to @(see
  lp-section-2).  Otherwise, we strongly recommend that you read @(see
  introduction-to-apply$) and then @(tsee apply$) before reading about
  @('loop$').</p>

  <p>(Return to the <see topic='@(url lp-section-0)'>Table of
  Contents</see>.)</p>")
other
(defxdoc lp-background-review-1
  :parents (lp-section-1)
  :short "Background review of basic ACL2 knowledge"
  :long "<p>Here are some questions to review basic features of ACL2.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>Consider the expression below and answer the following questions about it,
  without running ACL2!  We're looking for informal answers largely in
  agreement with ours, not perfect answers.  If you want to see the questions
  together with our answers, see @(see
  lp-background-review-1-answers).</p>

  @({
  (defun abc (x)
    (declare (xargs :mode :program
                    :guard (true-listp x)))
    (cond
     ((endp x) nil)
     (t (cons (cons '? (car x))
              (abc (cdr x))))))
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>1: Informally, what happens if you type that expression at the
  top-level of the ACL2 read-eval-print loop?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>2: More formally, how does the utterance above affect the ACL2
  logic?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>3: A little bit of Lisp knowledge will tell you that all terms are either
  variables, constants (usually quoted), or calls of functions, where calls are
  of the form @('(fn a1 ... an)'), where @('fn') is a function symbol or
  @('lambda') object that takes @('n') arguments and the @('ai') are terms.
  But the @('cond') expression above is not of this form.  @('Cond') is a macro
  that translates into a formal term.  What formal term does it translate
  to?  And if you didn't know, how would you find out?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>4: Let @('x') be the object that prints as @('((A . 1) (B . 2) (C
  . 3))').  What is the value of @('(car x)') or is that a nonsensical
  question?  Several of the questions below are nonsensical!</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>5: Given the value of @('x') in question 4, what is the value of
  @('(true-listp x)')?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>6: Given the value of @('x') in question 4, what is the value of @('(cons
  '? (car x))')?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>7: Given the value of @('x') in question 4, what is the value of @('(cdr
  x)')?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>8: Recall we defined @('abc') above.  What is the value @('(abc '((a
  . 1) (b . 2) (c . 3)))')?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>9: What is the difference between @(''((a . 1) (b . 2) (c . 3))') and
  @('((A . 1) (B . 2) (C . 3))')?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>10: What is the value of @('(abc ((a . 1) (b . 2) (c
  . 3)))')?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>11: How would you explain what @('abc') is, i.e., how it &ldquo;works&rdquo; or
  what it &ldquo;does?&rdquo;</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>12: What is the value of @('(abc 3 4 5)')?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>13: What is the value of @('(abc '(3 . 4))')?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>14: How do you get ACL2 to print the value of @('(abc '(3 . 4))')?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>15: How can you upgrade @('abc') from a @(':program') mode function to
  a @(':logic') mode function?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>16: What is the axiom added to ACL2 when @('abc') is upgraded?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>17: Is @('(true-listp (abc x))') a theorem in ACL2?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>18: What would you type to get ACL2 to try to prove it?</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>19: How would you describe the behavior of the @(':logic') function
  @('def') below?  By the way, we're naming certain functions in these reviews
  with consecutive letters of the alphabet, e.g., @('abc'), @('def'), @('ghi'),
  @('jkl'), @('mno'), etc.  These names are not mnemonic or acronyms.  Don't
  read anything into the names!</p>

  @({
  (defun def (x)
    (if (endp x)
        nil
        (append (def (cdr x)) (list (car x)))))
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>20: Define @('sq') to square a number.  E.g., @('(sq 9)') returns @('81')
  and @('(sq -1/2)') returns @('1/4').</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>21: How would you describe the behavior of @('sq*') below?</p>

  @({
  (defun sq* (x)
    (if (endp x)
        nil
        (cons (sq (car x))
              (sq* (cdr x)))))
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>22: What would you type to make ACL2 prove the following conjecture?</p>

  @({
  (equal (sq* (def x)) (def (sq* x)))
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;
  <p>23:  Prove @('(nat-listp (ghi 0 max))'), where</p>

  @({
  (defun ghi (i max)
    (declare (xargs :measure (nfix (- (+ 1 (nfix max)) (nfix i)))))
    (let ((i (nfix i))
          (max (nfix max)))
      (cond ((> i max) nil)
            (t (cons i (ghi (+ 1 i) max))))))
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>For our answers see @(see lp-background-review-1-answers).  If
  your answers don't basically agree with ours, you're probably not yet ready
  to read this material on @(see loop$).  We recommend that you read the
  topic, @(see recursion-and-induction).</p>

  <p>If your answers largely agree with ours, go back to the @(see
  lp-section-1).</p>

  <p>(Return to the <see topic='@(url lp-section-0)'>Table of
  Contents</see>.)</p>")
other
(defxdoc lp-background-review-1-answers
  :parents (lp-section-1)
  :short "Answers to background review of basic ACL2 knowledge"
  :long "@({
  (defun abc (x)
    (declare (xargs :mode :program
                    :guard (true-listp x)))
    (cond
     ((endp x) nil)
     (t (cons (cons '? (car x))
              (abc (cdr x))))))
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>1: Informally, what happens if you type that expression at the
  top-level of the ACL2 read-eval-print loop?</p>

  <p>Answer: It defines @('abc') as a Lisp program.  Note the @('declare') that
  says the @(':mode') is @(':program').  By the way, when Lisp and ACL2 read
  symbols, like @('abc'), @('x'), @('declare'), etc., they automatically
  convert them to UPPERCASE.  So it doesn't matter if we write @('abc') or
  @('ABC'), or @('Abc'), etc.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>2: More formally, how does the utterance above affect the ACL2
  logic?</p>

  <p>Answer: It doesn't.  Defining a @(':program') introduces no axioms into
  the logic.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>3: A little bit of Lisp knowledge will tell you that all terms are either
  variables, constants (usually quoted), or calls of functions, where calls are
  of the form @('(fn a1 ... an)'), where @('fn') is a function symbol or
  @('lambda') object that takes @('n') arguments and the @('ai') are terms.
  But the @('cond') expression above is not of this form.  @('Cond') is a macro
  that translates into a formal term.  What formal term does the @('cond')
  expression translate to?  And if you didn't know, how would you find out?</p>

  <p>Answer: The expression</p>
  @({
  (cond
   ((endp x) nil)
   (t (cons (cons '? (car x))
            (abc (cdr x)))))
  })
  <p>translates to</p>
  @({
  (if (endp x)
      'nil
      (cons (cons '? (car x))
            (abc (cdr x))))
  })
  <p>To see the translation of an expression use @(tsee trans).</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>4: Let @('x') be the object that prints as @('((A . 1) (B . 2) (C . 3))').
  What is the value of @('(car x)') or is that a nonsensical question?  Several
  of the questions below are nonsensical!</p>

  <p>Answer: @('(car x)') is @('(A . 1)') if @('x') is @('((A . 1) (B . 2) (C
  . 3))').</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>5: Given the value of @('x') in question 4, what is the value of
  @('(true-listp x)')?</p>

  <p>Answer: @('T'), because @('x') is a nest of conses whose rightmost
  terminal is @('NIL').</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>6: Given the value of @('x') in question 4, what is the value of @('(cons
  '? (car x))')?</p>

  <p>Answer: @('(? A . 1)')</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>7: Given the value of @('x') in question 4, what is the value of @('(cdr
  x)')?</p>

  <p>Answer: @('((B . 2) (C . 3))')</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>8: What is the value @('(abc '((a . 1) (b . 2) (c . 3)))')?</p>

  <p>Answer: @('((? A . 1) (? B . 2) (? C . 3))')</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>9: What is the difference between @(''((a . 1) (b . 2) (c . 3))') and
  @('((A . 1) (B . 2) (C . 3))')?</p>

  <p>Answer: @(''((a . 1) (b . 2) (c . 3))') is a constant term that evaluates
  to the list @('((A . 1) (B . 2) (C . 3))').  The quote mark in front an
  object forms a term that evaluates to that object.  And remember, case is
  generally irrelevant in symbols.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>10: What is the value of @('(abc ((a . 1) (b . 2) (c
  . 3)))')?</p>

  <p>Answer: That's a nonsensical question.  @('(abc ((a . 1) (b . 2) (c
  . 3)))') is not a well-formed term.  For example, @('(a . 1)') is not a
  function symbol or a @('lambda') expression, or a macro.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>11: How would you explain what @('abc') is, i.e., how it &ldquo;works&rdquo; or
  what it &ldquo;does?&rdquo;</p>

  <p>Answer: The symbol @('ABC') is the name of a Lisp program that takes one
  argument and returns one result.  It can be run, but nothing can be proved
  about it because there are no axioms defining it.  When @('abc') is called on
  @('x') it copies the @('cdr')-chain of @('x'), adding the question mark
  symbol to each new element.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>12: What is the value of @('(abc 3 4 5)')?</p>

  <p>Answer: Nonsensical. @('ABC') takes only one argument, not three.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>13: What is the value of @('(abc '(3 . 4))')?</p>

  <p>Answer: Actually, it is @('((? . 3))'), but ACL2 won't evaluate @('(abc
  '(3 . 4))') in the default configuration of the top-level read-eval-print
  loop because @('(3 . 4)') is not a @(tsee true-listp).  The guard on @('ABC')
  stipulates that the argument to @('ABC') is &ldquo;supposed&rdquo; to be a
  @('true-listp').  So the read-eval-print loop causes a guard violation error.
  We explain why the value of @('(abc '(3 . 4))') is actually @('((? . 3))') in
  the next answer.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>14: How do you get ACL2 to compute and print the value of @('(abc '(3
  . 4))')?</p>

  <p>Answer: The top-level read-eval-print loop has a parameter that controls
  whether ACL2 checks the guards or not.  By default, that parameter is set to
  @('T'), meaning it does check guards.  But by executing
  @('(set-guard-checking nil)') the parameter is set to @('NIL') and then
  guards are not checked.  With that setting, ACL2 evaluation just ignores the
  guard and runs the body of the program.</p>

  <p>So here is how @('(abc '(3 . 4))') is evaluated.  First, it checks whether
  @(tsee endp) holds on @('(3 . 4)').  The definition of @('endp') is
  @('atom'), which means &ldquo;is not a @(tsee cons) pair,&rdquo; and @('(3 . 4)') is a
  @('cons') pair.  So the answer to the @('endp') test is @('NIL') and the
  execution of @('(abc '(3 . 4))') branches to the @('(cons (cons '? (car
  x)) (abc (cdr x)))'), where @('x') is @('(3 . 4)').</p>

  <p>But the @('car') and @('cdr') of the pair @('(3 . 4)') are @('3') and
  @('4') respectively.  So the value of @('(abc '(3 . 4))') is @('(cons (cons
  '? 3) (abc 4))').</p>

  <p>But what is the value of @('(abc 4)')?  @('(Endp 4)') is @('T') because
  @('4') is an atom.  So the value of @('(cons (cons '? 3) (abc 4))') is
  @('(cons (cons '? 3) NIL)'), which is printed as @('((? . 3))').</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>15: How can you upgrade @('abc') from a @(':program') mode function to
  a @(':logic') mode function?</p>

  <p>Answer: Invoke @(tsee verify-termination) like this @('(verify-termination abc)').</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>16: What is the axiom added to the ACL2 logic when @('abc') is
  upgraded?</p>

  <p>Answer:</p>
  @({
  <b>Definitional Axiom for ABC</b>
  (abc x)
  =
  (if (endp x)
      nil
      (cons (cons '? (car x))
            (abc (cdr x)))).
  })

  <p>Note that the guard is irrelevant in the logic.  @('(Abc x)') is always
  equal to the right-hand side of the axiom above (the &ldquo;body&rdquo; of @('abc')),
  regardless of what @('x') is.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>17: Is @('(true-listp (abc x))') a theorem in ACL2?</p>

  <p>Answer: Yes!  It may not seem so because the @('defun') of @('abc')
  mentions the @(':guard') of @('(true-listp x)') and yet the conjecture here
  doesn't constrain @('x').  But guards of ACL2 functions are logically
  irrelevant.  The Definitional Axiom added for @('abc') does not mention the
  guard.  So @('(true-listp (abc x))') is a theorem no matter what @('x')
  is!</p>

  <p>Proof of @('(true-listp (abc x))') by induction on @('x'):</p>
  @({
  Base Case: (atom x)                  ; i.e., x is not a consp
  (true-listp (abc x))
  =                                    ; def abc
  (true-listp (if (endp x) nil ...))
  =                                    ; def endp and (atom x).
  (true-listp (if T nil ...))
  =                                    ; axiom about IF
  (true-listp nil)
  =                                    ; def true-listp
  T

  Induction Step: (consp x)
  Induction Hyp:  (true-listp (abc (cdr x)))

  (true-listp (abc x))
  =                                    ; def abc
  (true-listp (if (endp x) nil (cons (cons '? (car x)) (abc (cdr x)))))
  =                                    ; def endp and (consp x)
  (true-listp (if NIL nil (cons (cons '? (car x)) (abc (cdr x)))))
  =                                    ; axiom about IF
  (true-listp (cons (cons '? (car x)) (abc (cdr x))))
  =                                    ; def true-listp
  (true-listp (abc (cdr x)))
  =                                    ; Induction Hyp
  T

  Q.E.D.
  })

  <p>If you ask ACL2 to do the proof (see the next question) its proof doesn't
  mention induction.  That's because when @('abc') was defined ACL2 does a
  little inductive reasoning to deduce the &ldquo;type&rdquo; of the output and deduced
  that it is always a @('true-listp').  That type inference essentially does
  the inductive proof above.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>18: What would you type to get ACL2 to try to prove it?</p>

  <p>Answer:</p>

  @({
  (thm (true-listp (abc x)))
  })
  <p>or</p>
  @({
  (defthm little-theorem-about-abc
    (true-listp (abc x)))
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>19: How would you describe the behavior of the @(':logic') function
  @('def') below?  By the way, we're naming certain functions in these reviews
  with consecutive letters of the alphabet, e.g., @('abc'), @('def'), @('ghi'),
  @('jkl'), @('mno'), etc.  These names are not mnemonic or acronyms.  Don't
  read anything into the names!</p>

  @({
  (defun def (x)
    (if (endp x)
        nil
        (append (def (cdr x)) (list (car x)))))
  })

  <p>Answer: It reverses @('x'), i.e., it returns a list containing the
  elements of @('x') in reverse order.  E.g., @('(def '(a b c))') returns @('(C
  B A)').</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>20: Define @('sq') to square a number.  E.g., @('(sq 9)') returns @('81')
  and @('(sq -1/2)') returns @('1/4').</p>

  <p>Answer:</p>

  @({
  (defun sq (x) (* x x))
  })

  <p>We could add a declaration, like @('(declare (xargs :guard (rationalp
  x)))') or @('(declare (xargs :guard (acl2-numberp x)))').  But we've chosen
  to keep things simple here.</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>21: How would you describe the behavior of @('sq*') below?</p>

  @({
  (defun sq* (x)
    (if (endp x)
        nil
        (cons (sq (car x))
              (sq* (cdr x)))))
  })

  <p>Answer: It squares every element of @('x') and returns the list of those
  results in the same order.  E.g., @('(sq* '(1 2 3 -1/2 #c(0 1)))') is @('(1 4
  9 1/4) -1').</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>22: What would you type to make ACL2 prove the following conjecture?</p>

  @({
  (equal (sq* (def x)) (def (sq* x)))
  })

  <p>Answer:  To get ACL2 to try to prove the theorem you could type</p>

  @({
  (defthm sq*-def
    (equal (sq* (def x)) (def (sq* x))))
  })

  <p>But ACL2 would fail to find the proof unless you'd proved some lemmas
  about @('def').  You might see a &ldquo;checkpoint&rdquo; like</p>

  @({
  *** Key checkpoint under a top-level induction
      before generating a goal of NIL (see :DOC nil-goal): ***

  Subgoal *1/2''
  (IMPLIES (AND (CONSP X)
                (EQUAL (DEF (SQ* (CDR X)))
                       (SQ* (DEF (CDR X)))))
           (EQUAL (APPEND (SQ* (DEF (CDR X)))
                          (LIST (* (CAR X) (CAR X))))
                  (SQ* (APPEND (DEF (CDR X)) (LIST (CAR X))))))
  })

  <p>What would that suggest you do?</p>

  <p>What we'd do is prove the following lemma first and then try
  @('sq*-def').</p>

  @({
  (defthm sq*-append
    (equal (sq* (append a b))
           (append (sq* a) (sq* b))))
  })

  <p>When that lemma is available as a @(':')@(tsee rewrite) rule during the
  proof of @('sq*-def') the checkpoint above would be further simplified, the
  induction hypothesis of the @('sq*-def') conjecture would be used, and the
  proof of @('sq*-def') would succeed.</p>

  <p>The experienced ACL2 user would anticipate this in a simple problem
  like this one.  But in a messier problem the experienced user would just be
  emotionally prepared for the proof attempt to fail and inspect the checkpoints
  to try to figure out how to complete the proof.  See @(see the-method).</p>

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;
  <p>23:  Prove @('(nat-listp (ghi 0 max))'), where</p>

  @({
  (defun ghi (i max)
    (declare (xargs :measure (nfix (- (+ 1 (nfix max)) (nfix i)))))
    (let ((i (nfix i))
          (max (nfix max)))
      (cond ((> i max) nil)
            (t (cons i (ghi (+ 1 i) max))))))
  })

  <p>Answer:  You can't prove @('(nat-listp (ghi 0 max))') by induction
  with that @('0') in one of the controlling arguments.  You have to generalize
  first.</p>

  @({
  (defthm nat-listp-ghi-lemma
     (nat-listp (ghi i max)))

  (defthm nat-listp-ghi
     (nat-listp (ghi 0 max)))
  })

  &mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;

  <p>That completes the answers to this review of basic ACL2 knowledge.  If
  your answers don't largely agree with ours, you're probably not yet ready to
  read the material in the @(see loop$-primer).  We recommend that you take the
  &ldquo;Recursion and Induction&rdquo; course <b>(which should be somehow
  linked in here!)</b>.</p>

  <p>(Return to the <see topic='@(url lp-section-0)'>Table of
  Contents</see>.)</p>")
other
(defxdoc loop$-recursion
  :parents (loop$)
  :short "Defining functions that recur from within @('FOR') @('loop$') expressions"
  :long "<h3>Examples</h3>
  @({
  (defun$ nat-treep (x)
    (declare (xargs :loop$-recursion t
                    :measure (acl2-count x)))
    (cond
     ((atom x) (natp x))
     (t (and (true-listp x)
             (eq (car x) 'NATS)
             (loop$ for e in (cdr x) always (nat-treep e))))))

  (defun$ copy-nat-tree (x)
    (declare (xargs :loop$-recursion t
                    :measure (acl2-count x)))
    (cond
     ((atom x)
      (if (natp x)
          (if (equal x 0)
              0
              (+ 1 (copy-nat-tree (- x 1))))
          x))
     (t (cons 'nats
              (loop$ for e in (cdr x) collect (copy-nat-tree e))))))
  })

  <p>Notice that @('nat-treep') and @('copy-nat-tree') each contain a simple
  @('FOR') @(tsee loop$) (also see @(see for-loop$)) in which the function
  being defined is called recursively.  @('Copy-nat-tree') is a little more
  complicated than @('nat-treep') because @('copy-nat-tree') also contains a
  recursive call outside of any @('loop$').  Notice also that both events
  specify the @(tsee xargs) @(':loop$-recursion t') and explicitly provide a
  @(':measure').  The usual other @('xargs') are optional but
  @(':loop$-recursion t') is required if recursion is used inside a @('FOR')
  @('loop$') and the measure must be made explicit.</p>

  <p>Recursion is not allowed inside a @('DO') @('loop$') expression.  In fact,
  ACL2 disallows the use of @(':loop$-recursion') in the @('xargs') of any
  definition whose body contains a @('DO') @('loop$').  So this topic is only
  about @('FOR') @('loop$')s.</p>

  <p>Some examples of @('loop$')-recursive definitions may be found in the book
  @('projects/apply/loop-recursion-examples.lisp').</p>

  <p><b>Warning:</b> We advise you to use @(tsee defun$) rather than @(tsee
  defun) when introducing a @(':logic') mode @('loop$')-recursive function.
  When a @('loop$')-recursive function is introduced it is assigned a badge.
  This is required because we cannot translate the body of a
  @('loop$')-recursive function without a badge.  However, no warrant is
  assigned by @('defun').  But it is impossible to reason about
  applications (with @(tsee apply$)) of unwarranted functions.  Indeed, it is
  even impossible to execute such applications in the top-level ACL2
  read-eval-print loop.  See @(see guarantees-of-the-top-level-loop).  So a
  @(':logic') mode @('loop$')-recursive function &mdash; which is guaranteed to
  involve applications of itself with @('apply$') &mdash; can't be reasoned
  about or executed (except on data not exercising the recursive calls inside
  @('loop$')s).  These inconveniences can be avoided by using @('defun$') when
  introducing @(':logic') mode @('loop$')-recursive functions because
  @('defun$') expands to a @('defun') followed by a @(tsee defwarrant).</p>

  <p><b>Warning:</b> Even though the functions defined above are recursive,
  ACL2 does not generate induction schemes for them!  If you want to do
  inductive proofs about @('loop$')-recursive functions you must provide a
  suitable @(':induction') hint.  In addition, to be provable by induction,
  theorems about @('loop$')-recursive functions must be suitably general.  This
  topic is discussed further in @(see loop$-recursion-induction).</p>

  <h3>Restrictions</h3>

  <p>If a function being defined exhibits recursion from within a @(tsee loop$)
  body or within the @('WHEN') or @('UNTIL') clauses of a @('loop$') in a
  @(tsee defun) of <i>fn</i>, then the @('defun') must include an @(tsee xargs)
  declaration with @(':loop$-recursion t').  In addition,</p>

  <ul>

  <li>the @('xargs') declaration must include an explicit @(':measure'),</li>

  <li><i>fn</i> must not be part of a @(tsee mutual-recursion) clique,</li>

  <li>every formal of <i>fn</i> must be ``ordinary,'' e.g., not of @(tsee ilk)
  @(':FN') or @(':EXPR'),</li>

  <li><i>fn</i> must return a single value,</li>

  <li><i>fn</i>'s measure must be of type @(tsee natp) or be a lexicographic
  combination of natural numbers as defined by the @('llist') function in the
  Community Books at @('books/ordinals/'),</li>

  <li><i>fn</i> must be @(tsee tame), which implies it may not take or
  return @(tsee state) or @(tsee stobj)s,</li>

  <li>every quoted @(tsee lambda) object in the body of <i>fn</i> must be
  well-formed (see @(tsee well-formed-lambda-objectp)), which implies that
  every such @('lambda') object is tame and every function symbol, including
  <i>fn</i>, used in each must have a @(tsee badge),</li>

  <li>every quoted @('lambda') object in the body of <i>fn</i> that calls
  <i>fn</i> recursively must occur as the first argument of a @('loop$') scion
  and <i>not</i> in some arbitrary scion,</li>

  <li>there is at least one recursive call of <i>fn</i> inside a quoted
  @('lambda') object which means that the @('loop$-recursion t') declaration
  was actually necessary, and</li>

  <li>the necessary measure conjectures (see below) must be proved.</li>

  </ul>

  <p>These restrictions make a little more sense if you reflect on what has to
  be done to check and admit a @('loop$')-recursive function.  First, we assume
  that most ACL2 functions are not @('loop$')-recursive.  So to keep
  @('defun')-processing as fast as possible, we require you to declare when you
  are using @('loop$') recursion.  That declaration triggers additional
  checks.</p>

  <p>But before checks can begin, we have to translate the body of <i>fn</i>
  and since @('loop$')s translate into calls of @('loop$') scions on quoted
  @('lambda')s and those must be tame, and since some of those @('lambda')s
  involve calls of <i>fn</i>, we must assign a badge to <i>fn</i> even before
  we have translated its body.  We assign a badge that declares <i>fn</i> to
  take the appropriate number of ordinary inputs, to return one result, and be
  tame.  We check those requirements after <i>fn</i> has been admitted.</p>

  <p>Because the measure guessing heuristics of ACL2 do not look for calls
  inside of quoted @('lambda')s, the measure must be explicitly declared even
  if it @('acl2-count').</p>

  <p>To find every recursive call in a quoted @('lambda') object those objects
  must all be well-formed.  If such an object occurs as the first argument of a
  @('loop$') scion then we know it is only applied to elements of the
  @('loop$') scion's target.  Given that, we can investigate whether the
  recursive calls in the @('lambda') object are on smaller things.  But if a
  recursive call were to occur in a quoted @('lambda') object that was passed
  to some other kind of scion, we have no way to know (without extensive
  analysis) to what it might be applied.</p>

  <p>Some of these restrictions could be lifted with more analysis and coding.
  For example, we could change the specification for the @(':loop$-recursion')
  @('xargs') keyword so that instead of taking on a Boolean value it takes on a
  badge.  Then we could tentatively assign that badge to <i>fn</i> before
  processing and check it afterwards.  Our current thinking is to ask users to
  live with these restrictions and let us see whether @('loop$')-recursion is
  useful (almost certainly it will be), whether the community can develop proof
  techniques and tools to reason about them as effectively as we reason about
  conventional recursive functions (we're optimistic), and whether investing
  time in lifting some of these restrictions is worth it given all the other
  ways we could improve ACL2.</p>

  <h3>Measure Conjectures</h3>

  <p>Measure conjectures must be generated for the recursive calls inside
  @('loop$') bodies.  (We also generate conjectures for the recursive calls the
  other @('loop$')-expression components, e.g., the @('WHEN') clause, exactly
  analogously, but we speak of the @('loop$') body only below.  We also focus
  on simple @('loop$')s here but the conjectures described generalize to fancy
  @('loop$')s.)  Given a recursive call inside the body of a @('loop$') with
  iteration variable <i>v</i>, we first generate a new variable symbol,
  <i>v'</i>.  Certain terms, e.g., tests and arguments to recursive calls, will
  be extracted from within the body and used in the measure conjecture.  We
  rename <i>v</i> to <i>v'</i> in these terms to distinguish occurrences of
  <i>v</i> outside the @('loop$') from those inside.  The measure conjecture
  requires us to prove that the given measure decreases, as usual.  But the
  ruling tests are those ruling the @('loop$'), conjoined with the hypothesis
  that <i>v'</i> is a member of the target, conjoined with the (renamed) tests
  from inside the body ruling the recursive call.</p>

  <p>Below is an example.  We show only the measure conjectures generated from
  inside the @('loop$') because there are two recursive calls in the @('loop$')
  body.</p>

  @({
  (defun$ fn (v)
    (declare (xargs :loop$-recursion t
                    :measure (acl2-count x)))
    (cond
     ((natp v)
      ...)
     ((true-listp v)
      (loop$ for v in (target v) sum
             (if (and (integerp v) (< v 0))
                 (fn (- v))
                 (fn v))))
     (t ...)))
  })

  <p>Note that @('v') used both as the formal of @('fn') and as the iterative
  variable of the @('loop$').  In the measure conjectures below, the iterative
  variable has been renamed to @('nv0').  Two measure conjectures are generated
  from within the @('loop$'):</p>

  @({
  (implies (and (not (natp v))
                (true-listp v)
                (member-equal nv0 (target v))
                (and (integerp nv0) (< nv0 0)))
           (o< (acl2-count (- nv0))
               (acl2-count v)))

  (implies (and (not (natp v))
                (true-listp v)
                (member-equal nv0 (target v))
                (not (and (integerp nv0) (< nv0 0))))
           (o< (acl2-count nv0) (acl2-count v)))
  })

  <p>Note that these conjectures require that when @('fn') is called from
  within the @('loop$') the argument is smaller than the initial value of the
  formal.  Notice also that there is no <i>a priori</i> restriction on the size
  of @('(target v)').  However, because of the way @('fn') is used inside this
  particular example @('loop$'), there are restrictions on the size of the
  elements of @('(target v)').  These conjectures, along with those generated
  from calls outside the @('loop$') are sufficient to guarantee that @('fn')
  always terminates.</p>

  <p><b>Note:</b> Careful readers might note that the way we handle measure
  conjectures for @('loop$')s differs from the way we handle guard conjectures
  for @('loop$')s.  In @(tsee loop$) we explained that @('loop$')s are
  translated into calls of @('loop$') @(tsee scion)s on quoted @(tsee lambda)
  objects and that the guard conjectures for the @('lambda') are insensitive to
  the context in which the object appeared.  But the measure conjectures are
  sensitive to the context: tests from outside the @('loop$') are present in
  the measure conjectures.  This is deliberate.  Guard conjectures are context
  insensitive because the implementation caches compiled @('lambda') objects
  without remembering the contexts in which they first occurred.  Thus, a
  @('lambda') object generated by a @('loop$') may be called on anything and we
  cannot guarantee that the input guard to the @('lambda') object will be
  satisfied.  <i>But we can guarantee that the computation carried out by the
  @('lambda') will terminate!</i> The @('lambda') object generated for @('fn')
  above terminates no matter what it is called on -- even if called on elements
  not in @('(target v)') -- because @('fn') terminates.</p>

  <p>Finally, recall that @('loop$')-recursive functions do not automatically
  suggest induction schemes and that special care must be taken when
  formulating inductively provable conjectures about them.  See @(see
  loop$-recursion-induction).</p>")
other
(defxdoc loop$-recursion-induction
  :parents (loop$)
  :short "Advice on inductive theorems about @(tsee loop$)-recursive functions"
  :long "<p><b>Warning:</b> This documentation topic is fairly preliminary
  because we do not have a lot of experience yet with @(tsee apply$), @(tsee
  loop$), and @(tsee loop$-recursion).  We assume here that readers are familiar
  with the topics cited above.</p>

  <h3>Definductor</h3>

  <p>The principles sketched here are illustrated concretely in the tutorial
  community book @('projects/apply/copy-nat-tree.lisp').  As noted in that
  book, the inductions are hinted manually so the reader can see from first
  principles what is involved.  However, in the book @('projects/apply/top') we
  provide a utility that sometimes automates the creation of the inductive hint
  function and associates it with the given @('loop$')-recursive function.  See
  @(tsee definductor).  The examples worked manually in @('copy-nat-tree.lisp')
  are recapitulated towards the end of
  @('projects/apply/definductor-tests.lisp'), without the manually provided
  hints.  In addition, the book
  @('projects/apply/loop-recursion-examples.lisp') gives some other examples of
  loop$-recursive functions and inductive theorems about them.</p>

  <h3>Some Basic Principles for Inductive Proofs about @('Loop$')-Recursive Functions</h3>

  <p>If ACL2 did not have @('loop$'), functions defined in terms of
  @('loop$')-recursion would have to be defined with @(tsee mutual-recursion).
  Reconsider the example presented in @(tsee loop$-recursion).</p>

  @({
  (defun$ nat-treep (x)
    (declare (xargs :loop$-recursion t
                    :measure (acl2-count x)))
    (cond
     ((atom x) (natp x))
     (t (and (true-listp x)
             (eq (car x) 'NATS)
             (loop$ for e in (cdr x) always (nat-treep e))))))

  (defun$ copy-nat-tree (x)
    (declare (xargs :loop$-recursion t
                    :measure (acl2-count x)))
    (cond
     ((atom x)
      (if (natp x)
          (if (equal x 0)
              0
              (+ 1 (copy-nat-tree (- x 1))))
          x))
     (t (cons 'nats
              (loop$ for e in (cdr x) collect (copy-nat-tree e))))))
  })

  <p>Without @('loop$') the latter function would have to be defined this way.
  We name it @('mr-copy-nat-tree'), where the ``@('mr')'' reminds us this is
  part of a mutually recursive clique.</p>

  @({
  (mutual-recursion
   (defun mr-copy-nat-tree (x)
     (cond
      ((atom x)
       (if (natp x)
           (if (equal x 0)
               0
               (+ 1 (mr-copy-nat-tree (- x 1))))
           x))
      (t (cons 'nats
               (mr-copy-nat-tree-list (cdr x))))))

   (defun mr-copy-nat-tree-list (x)
     (cond
      ((endp x) nil)
      (t (cons (mr-copy-nat-tree (car x))
               (mr-copy-nat-tree-list (cdr x)))))))
  })

  <p>Note that we define @('mr-copy-nat-tree') by copying the definition of
  @('copy-nat-tree') (renaming recursive calls appropriately) but replacing the
  use of @('loop$') in @('copy-nat-tree') with a call of a mutually-recursive
  function here called @('mr-copy-nat-tree-list').  We call
  @('mr-copy-nat-tree-list') the ``list counterpart'' of @('mr-copy-nat-tree').
  However, in general there may be more than just two functions in the clique
  and so we refer generically to @('mr-copy-nat-tree-list') as a ``co-member''
  of the clique.</p>

  <p>How would you prove theorems about @('mr-copy-nat-tree')?  Four principles
  are known to most ACL2 users of @('mutual-recursion').  These principles
  apply to @('loop$')-recursive functions as well as to mutually recursive
  ones.  We state them here in terms of both kinds of definitions.</p>

  <ul>

  <li>While simple recursive functions suggest ``appropriate'' inductions,
  mutually recursive functions and @('loop$')-recursive functions do not.  If
  you want to prove a theorem about such functions you have to arrange some
  kind of induction hint.</li>

  <li>You can't generally prove an isolated theorem about a single member of a
  mutually recursive clique or a @('loop$')-recursive function.  Instead, you
  must state a conjecture about every member of the clique, conjoin all those
  theorems together, and prove them inductively all at once.  Applied to
  proving a theorem about @('mr-copy-nat-tree') this advice means we must
  conjoin the theorem about that function with ``the same'' theorem about
  @('mr-copy-nat-tree-list'), and more generally with theorems about every
  co-member of the clique.  Of course, what we mean by ``the same'' theorem
  about different members of the clique depends on what each member contributes
  to the overall computation.  Applied to the @('loop$')-recursive function
  @('copy-nat-tree') this advice means we must simultaneously prove a theorem
  about every @('loop$') in the function.</li>

  <li>Inductively provable theorems must be sufficiently general.  When dealing
  with a mutually recursive clique, each conjunct must address itself to the
  ``general'' call of the co-member in question, e.g., to
  @('(mr-copy-nat-tree-list x)') not to the specific call inside
  @('mr-copy-nat-tree'), which is @('(mr-copy-nat-tree-list (cdr x))').  When
  dealing with a @('loop$')-recursive function, each conjunct must address
  itself to the general target, not to specific target in the @('loop$')
  recursive function.  In the case of the @('loop$')-recursive function
  @('copy-nat-tree') we need a conjunct about @('(loop$ for e in x
  collect (copy-nat-tree e))'), not about @('(loop$ for e in (cdr x)
  collect (copy-nat-tree e))').</li>

  <li>Finally, the induction scheme used must provide an inductive hypothesis
  about every recursive call of every co-member of the clique or, in the case
  of @('loop$')-recursion, about every recursive unwinding of each
  @('loop$').</li>

  </ul>

  <p><b>Remember:</b> Because @('loop$')-recursive functions call themselves
  recursively with @('apply$'), any theorem about a @('loop$') recursive
  function must almost certainly include a warrant hypothesis for that
  function!</p>

  <p>We illustrate these principles in the community book
  @('projects/apply/copy-nat-list.lisp').</p>")
other
(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>

 <p><i>Remark.</i> The paragraph above mentions ``the conclusion of the rule''
 as @('(equiv lhs rhs)').  The rule's conclusion is actually produced from a
 naive version @('(equiv lhs0 rhs)') of the conclusion by expanding away all
 @(see lambda) applications in @('lhs0').  If @('lhs0') and @('lhs') are
 distinct (i.e., if there is any such lambda expansion) and also the
 loop-stopper field is calculated as @('nil') as described above, then a second
 attempt to calculate the loop-stopper is made using @('lhs0') in place of
 @('lhs').</p>")
other
(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') states that its argument is a
 character.</p>

 <p>@('Lower-case-p') is a Common Lisp function.  See any Common Lisp
 documentation for more information.  Note that the value returned may depend
 on the host Lisp; see @(see soundness), specifically Example 1 in the Section,
 &ldquo;Examples of divergence among Lisp implementations&rdquo;.</p>

 @(def lower-case-p)")
other
(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>")
other
(defxdoc macro-aliases-table
  :parents (macros)
  :short "A @(see table) used to associate function names with macro names"
  :long "@({
 Example Form:
 (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)).

 General Form:

 (table macro-aliases-table 'macro-name 'function-name)
 })

 <p>or more generally</p>

 @({
 (table macro-aliases-table macro-name-form function-name-form)
 })

 <p>where @('macro-name-form') and @('function-name-form') evaluate to values
 @('MAC') and @('FN'), subject to the following requirements.</p>

 <ul>

 <li>@('MAC') is a symbol that is a macro name.</li>

 <li>@('FN') is a symbol.</li>

 <li>@('FN') is either a function symbol or else a symbol that does not have a
 definition (a <i>new name</i>).  In particular, @('FN') is not a macro
 name.</li>

 </ul>

 <p>After admitting the @(see table) event displayed above, we may say that
 @('MAC') is a <i>macro-alias for</i> @('FN').</p>

 <h3>Further Explanation</h3>

 <p>See @(see table) for a general discussion of tables and the @('table')
 @(see event), which is used to manipulate tables.  The table, @(tsee
 macro-aliases-table), is an alist that can associate macro symbols with
 function symbols, so that macro names may be used as runic designators (see
 @(see theories) and discussion below).  For a convenient way to add entries to
 this @(see table), see @(see add-macro-alias), which allows the second
 argument to be, itself, a macro-alias.  To remove entries conveniently from
 the @(see table), see @(see remove-macro-alias).</p>

 <p>As hinted above, this @(see table) is used by theory functions; see @(see
 theories).  For example, in order that @('(disable append)') be interpreted as
 @('(disable binary-append)'), it suffices that @('(table macro-aliases-table
 'append 'binary-append)'), has been executed.  In fact, this @(see table) does
 indeed establish many of the macros provided by the ACL2 system as
 macro-aliases, such as establishing @(tsee append) as a macro-alias for @(tsee
 binary-append).  This only takes place when the macro is &ldquo;essentially
 the same thing as&rdquo; a corresponding function; for example, @('(append x
 y)') and @('(binary-append x y)') represent the same term, for any expressions
 @('x') and @('y').</p>

 <p>Note that the value @('FN') of @('function-name-form') (above) is allowed
 to be a symbol to be defined later as a function symbol.  The following
 examples illustrate some approaches that work and some that do not.</p>

 @({
 ;;;;;;;;;;
 ;;; Example 1: No errors, with function defined before setting the table.
 ;;;;;;;;;;

 (defun fn (x) x)
 (defmacro mac (x) (list 'fn x))
 (table macro-aliases-table 'mac 'fn) ; or (add-macro-alias mac fn)
 (in-theory (disable mac))

 ;;;;;;;;;;
 ;;; Example 2: No errors, with function defined after setting the table.
 ;;;;;;;;;;

 (defmacro mac (x) (list 'fn x))

 ; Legal, even though fn is not yet defined:
 (table macro-aliases-table 'mac 'fn) ; or (add-macro-alias mac fn)

 (defun fn (x) x)
 (in-theory (disable mac))

 ;;;;;;;;;;
 ;;; Example 3: ERROR.
 ;;;;;;;;;;

 (defun fn (x) x)
 (defmacro mac1 (x) (fn x))
 (defmacro mac2 (x) (list 'mac1 x))

 ; BAD, since the table event above anticipates fn to be defined as
 ; a function, not a macro (but, no error yet) -- but not (yet) an error:
 (table macro-aliases-table 'mac2 'mac1) ; or (add-macro-alias mac2 mac1)

 ; ERROR, since mac2 does not designate rules, because it aliases a macro:
 (in-theory (disable mac2))

 ; OK, but too late to help with that in-theory event; see below:
 (table macro-aliases-table 'mac1 'fn) ; or (add-macro-alias mac1 fn)

 ; ERROR, since mac2 is still associated with mac1, not with fn:
 (in-theory (disable mac2))

 ;;;;;;;;;;
 ;;; Example 4: Fixed version of Example 3.
 ;;;;;;;;;;

 (defun fn (x) x)
 (defmacro mac1 (x) (fn x))
 (defmacro mac2 (x) (list 'mac1 x))
 (add-macro-alias mac1 fn); or (table macro-aliases-table 'mac1 'fn)

 ; The following is equivalent to (add-macro-alias mac2 fn), since
 ; mac1 is a macro-alias for fn by virtue of the preceding event.
 (add-macro-alias mac2 mac1)

 ; Success:
 (in-theory (disable mac2))
 })")
other
(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 Common Lisp, respecting the order shown:</p>

 <ul>

 <li>@('&whole x')<br/>
 @('X') does not represent an actual parameter; rather, it is bound to the
 entire macro call.
 </li>

 <li>@('&optional x1 x2 ...')<br/>
 The actual for any @('xi') may be omitted, in which case the actual for every
 @('xj') with @('j > i') must also be omitted.
 </li>

 <li>@('&rest x')<br/>
 @('X') does not represent an actual parameter; rather, it is bound to the list
 of all actuals provided from that position onward.
 </li>

 <li>@('&body x')<br/>
 This is identical to @('&rest x').
 </li>

 <li>@('&key x')<br/>
 The call may have a keyword argument for @('x') by including @(':x val') after
 all required actual parameters, in which case the formal @('x') is bound to
 the actual @('val').
 </li>

 <li>@('&allow-other-keys')<br/>
 Keyword arguments not specified by @('&key') are allowed but ignored.
 </li>

 </ul>

 <p>ACL2 does not support the Common Lisp lambda-list keywords @('&aux') and
 @('&environment').  In addition, there are 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') or, equivalently, @('(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 (hence so does ACL2) 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>")
other
(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>")
other
(defxdoc macrolet
  :parents (basics acl2-built-ins)
  :short "Local binding of macro symbols"
  :long "<p>See @(see flet) for an analogous utility for defining functions
 locally.</p>

 @({
 Example Form:
 (defun f1 (x)
   (macrolet ((mac (a) (list 'quote a)))
     (cons x (mac x))))
 })

 <p>The Example Form above is equivalent to the following, in which the call of
 local macro @('mac') has been expanded.</p>

 @({
 (defun f1-alt (x)
   (cons x (quote x)))
 })

 <p>The General Forms are similar to those of @(tsee flet).</p>

 @({
 General Forms:
 (macrolet (def1 ... defk) body)
 (macrolet (def1 ... defk) declare-form1 .. declare-formk body)
 })

 <p>where @('body') is a term, and each @('defi') is a definition as in @(tsee
 defmacro) but with the leading @('defmacro') symbol omitted.  See @(see
 defmacro), but see @(see declare) for the declarations permitted directly
 under the @('defi').  On the other hand, regarding the @('declare-formi') (if
 any are supplied): 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').  Unlike the
 related utility @(tsee flet), those @('inline') and @('notinline')
 declarations are unlikely to have any effect.</p>

 <p>The innermost @(tsee flet) or @('macrolet') binding of a symbol, @('f'),
 above a call of @('f'), is the one that provides the definition of @('f') for
 that call.  Note that neither @('flet') nor @('macrolet') provide recursion:
 that is, the definition of @('f') in an @('flet') or @('macrolet') binding of
 @('f') is ignored in the body of that binding.</p>

 <p>The following requirements are imposed by Common Lisp and enforced by
 ACL2.</p>

 <ul>

 <li>Every variable occurring in the body of a @('defi') must be a formal
 parameter name of that @('defi').</li>

 <li>No function or macro symbol called in the body of a @('defi') may be
 defined by a superior @('flet') or @('macrolet') binding.  (Not every Common
 Lisp implementation includes this restriction for superior @('macrolet')
 bindings, but at least one (GCL) does so we include it in ACL2.)</li>

 </ul>

 <p>Although @('macrolet') 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 symbol.</li>

 <li>Each @('defi') must bind a symbol that is a legal name for an ACL2 macro.
 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>When an expression @('(macrolet (... defi ...) ...)') occurs in the body
 of a @('DO') @(tsee loop$) expression, nevertheless constructs such as
 @('PROGN') and @('SETQ') that ACL2 permits in @('DO') @('loop$') bodies are
 not permitted in @('defi') (unless they occur within the scope of a @('DO')
 @('loop$') expression in that body).</li>

 </ul>

 <p>@('Macrolet') bindings are evaluated in parallel.  Consider the following
 example.</p>

 @({
 (defun f1 (x) (cons x 'x))
 (macrolet ((f1 (x) x)
            (f2 () (list 'quote
 ; The following reference is to the global f1,
 ; not to the identity macro just above.
                         (f1 3))))
   (f2))
 })

 <p>The @('macrolet') form above evaluates to @('(3 . x)'), not to 3, as
 explained in the comment above.  Here is a somewhat analogous form that one
 might expect to evaluate to 3, but that is not the case; see below.</p>

 @({
 (macrolet ((f1 (x) x))
   (macrolet ((f2 () (list 'quote (f1 3))))
     (f2)))
 })

 <p>The body of @('f2') calls a symbol, @('f1'), that is bound by a superior
 @('macrolet') binding.  As noted above, this is illegal (also for superior
 @('flet') bindings).</p>

 <p>Under the hood, ACL2 expands away @('macrolet') bindings.  The following
 example illustrates this point.</p>

 @({
 ACL2 !>:trans (macrolet ((mac (a) (list 'cons a a)))
                 (car (mac b)))

 (CAR (CONS B B))

 => *

 ACL2 !>
 })

 <p>@('Macrolet') is part of Common Lisp.  See any Common Lisp documentation
 for more information.  We conclude by pointing out an important aspect of
 @('macrolet') shared by ACL2 and Common Lisp: The binding is lexical, not
 dynamic.  That is, the @('macrolet') binding of a symbol only applies to calls
 of that symbol in the body of the @('macrolet'), not other calls made in the
 course of evaluation.  See @(see flet) for discussion of this point.</p>")
other
(defxdoc macros
  :parents (acl2)
  :short "Macros allow you to extend the syntax of ACL2.")
other
(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 @(see 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 @(see multiple-value)d
 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 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>")
other
(defxdoc mailing-lists
  :parents (acl2 about-acl2 community)
  :short "Mailing lists for ACL2 users"
  :long "<p>There are the following mailing lists for ACL2 users.  You can
 post messages to these lists only if you are a member, but anyone can view the
 archives.

 <ul>
 <li><b>acl2 list</b>: General ACL2 list for users and others interested in ACL2
   <ul>
     <li>To post: <tt><a href='mailto:acl2@utlists.utexas.edu'>acl2@utlists.utexas.edu</a></tt></li>
     <li>To subscribe, unsubscribe, or view archives:
       <tt><a href='https://utlists.utexas.edu/sympa/info/acl2'>https://utlists.utexas.edu/sympa/info/acl2</a></tt></li>
   </ul>
 </li>

 <li><b>acl2-help list</b>: ACL2 help list, for questions about using
   ACL2 <font color='red'>(recommended for new users)</font>
   <ul>
     <li>To post: <tt><a href='mailto:acl2-help@utlists.utexas.edu'>acl2-help@utlists.utexas.edu</a></tt></li>
     <li>To subscribe, unsubscribe, or view archives:
       <tt><a href='https://utlists.utexas.edu/sympa/info/acl2-help'>https://utlists.utexas.edu/sympa/info/acl2-help</a></tt></li>
   </ul>
 </li>

 <li><b>acl2-books list</b>: Mailing list for discussion of
 cutting-edge developments in ACL2 and the ACL2 Community Books
   <ul>
     <li>To post: <tt><a
 href='mailto:acl2-books@googlegroups.com'>acl2-books@googlegroups.com</a></tt></li>
     <li>To subscribe, unsubscribe, or view archives:
       <tt><a href='https://groups.google.com/forum/#!forum/acl2-books'>https://groups.google.com/forum/#!forum/acl2-books</a></tt></li>
   </ul>
 </li>

 </ul></p>

 <p>Finally, please report bugs in ACL2 to
 <a href='mailto:kaufmann@cs.utexas.edu'>Matt Kaufmann</a>.</p>

 <p>See @(see community) for ways to connect with other ACL2 users,
 get help with ACL2, and contribute to improving ACL2 and its
 @(see community-books).</p>
 ")
other
(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>")
other
(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)")
other
(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 @(see state) and logical @(see world).  In essence,
 the expression @('(make-event form)') replaces itself with the result of
 evaluating @('form') &mdash; let's call that result @('ev') &mdash; 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>We assume basic familiarity with the ACL2 <i>state</i>.  For relevant
 background, see @(see state) and perhaps see @(see
 programming-with-state).</p>

 <p>There are several simple examples below.  For examples that can give
 additional insight into the use of @('make-event') for tool development, see
 @(see make-event-example-1) and @(see make-event-example-2).  Also see the
 @('make-event/') subdirectory of the ACL2 @(see community-books) for more
 examples, for example, @('books/make-event/search-generation.lisp').</p>

 <p>We break this documentation into the following sections.</p>

 <ul>

 <li><b>Introduction</b></li>

 <li><b>Detailed Documentation</b></li>

 <li><b>Error Reporting</b></li>

 <li><b>Restriction to Event Contexts</b></li>

 <li><b>Examples Illustrating How to Access State</b></li>

 <li><b>Advanced Expansion Control</b></li>

 </ul>

 <p>We begin with an introduction, which focuses on examples and introduces the
 key notion of ``expansion phase''.</p>

 <h3>Introduction</h3>

 <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 the formal parameter
 @('"STATE"') is bound to the syntactic object in the macro call, not to the
 actual ACL2 @(see state); see @(see defmacro).  You can try to experiment with
 other such direct methods to define a macro that accesses the ACL2 state, 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 is a log that may help to explain this macro, assuming it has been
 defined as displayed just above.</p>

 @({
 ACL2 !>:trans1 (define-world-length-constant *foo*)
  (MAKE-EVENT (LIST 'DEFCONST
                    '*FOO*
                    (LENGTH (W STATE))))
 ACL2 !>(LIST 'DEFCONST
              '*FOO*
              (LENGTH (W STATE)))
 (DEFCONST *FOO* 109707)
 ACL2 !>
 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.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
  *FOO*
 ACL2 !>*foo*
 109707
 ACL2 !>:pe *foo*
            2:x(DEFINE-WORLD-LENGTH-CONSTANT *FOO*)
               
 >              (DEFCONST *FOO* 109707)
 ACL2 !>(length (w state))
 109713
 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*
 109713
 ACL2 !>:pe *bar*
            3:x(DEFINE-WORLD-LENGTH-CONSTANT *BAR*)
               
 >              (DEFCONST *BAR* 109713)
 ACL2 !>(length (w state))
 109719
 ACL2 !>
 })

 <p>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 ACL2 world at all, but instead saves the length of the
 world into a state global variable (see @(see assign)).</p>

 @({
  (make-event
   (er-progn (assign my-world-length (length (w state)))
             (value '(value-triple nil))))
 })

 <p>Notice that this time, the value returned by the expansion phase is not a
 single value; rather, it 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, @('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))
 109700
 ACL2 !>(make-event
             (er-progn (assign my-world-length (length (w state)))
                       (value '(value-triple nil))))

 Summary
 Form:  ( MAKE-EVENT (ER-PROGN ...))
 Rules: NIL
 Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
  NIL
 ACL2 !>(length (w state))
 109700
 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.  Consider again
 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.  That is because the expansion,
 @('(DEFCONST *FOO* 109700)'), is recorded in the book's @(see certificate) and
 re-used during a subsequent @(tsee include-book).</p>

 <p>However, the keyword @(':check-expansion') may be given the value @('t') so
 that the expansion is done even during @('include-book'), which comes with a
 check that the result is the same as it was during book certification.  This
 keyword 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)
 })

 <h3>Detailed Documentation</h3>

 @({
  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
              :SAVE-EVENT-DATA save)
 })

 <p>where @('chk') is @('nil') (the default), @('t'), or the intended
 ``expansion result'' from the evaluation of @('form') (as explained below);
 @('obj') is an arbitrary ACL2 object, used only in reporting errors in
 expansion, i.e., in the evaluation of form; and @('save') is arbitrary but is
 considered only as either @('nil') or non-@('nil').  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')
 and :SAVE-EVENT-DATA keywords.</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/std/testing/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 during expansion (see @(see ld-skip-proofsp)) if
 keyword @(':CHECK-EXPANSION') is supplied a non-@('nil') value or a certain
 attachment is made (see (4) below).</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 @(see book-name)s to indicate @(see
 full-book-name)s.  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)))
               (DEFUN FOO (X) X))
 })

 <h3>Error Reporting</h3>

 <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>

 <h3>Restriction to Event Contexts</h3>

 <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.</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>

 <h3>Avoiding large @('make-event') forms in @(see certificate) files</h3>

 <p>The @(see certificate) file for a book contains expansions of
 @('make-event') forms from the book.  (Those interested may find details about
 this in an Implementation Note about ``The book expansion'' in the
 documentation topic, @(see make-event-details).)  Those expansions can be very
 large if one is not careful.  Consider the difference between the following
 two events.</p>

 @({
 (make-event
  `(defconst *foo* ,(length (w state))))

 (make-event
  `(defconst *foo* (length ',(w state))))

 })

 <p>The first generates an expansion such as @('(defconst *foo* 122700)')
 (where the numeric value depends on the @(see world) in which the
 @('make-event') form is evaluated).  The second, however, generates an
 expansion of the form @('(defconst *foo* (length '<wrld>))'), where @('<wrld')
 is an ACL2 world &mdash; a very large structure.  The @('.cert') file for a
 book containing the second form will therefore contain many megabytes.
 Moreover, with the second form the length of that world will need to be
 computed when the book is included (which may be fast, but could be slow for a
 different such computation).</p>

 <h3>Examples Illustrating How to Access State</h3>

 <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.  Let us look at some examples and then consider a
 restriction for many built-in state globals.</p>

 <p>First consider the following.  Notice that expansion modifies a state
 global, @('my-global'), during @('make-event') expansion (see @(see assign));
 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>Because @('make-event') creates @(see event) forms that can go into @(see
 books) and @(tsee encapsulate) events, you can use @('make-event') forms such
 as those above to modify the ACL2 @(see state) using books and
 @('encapsulate') events.  The most common way to do this is for the
 @('make-event') expansion to be a trivial event form such as @('(value-triple
 nil)'), such as the following.</p>

 @({
 (make-event (er-progn (assign my-list-of-10 (make-list 10))
                       (value '(value-triple nil))))
 })

 <p>The desired effect will take place during calls of @(tsee certify-book),
 but it will generally <b>not</b> take place during @(tsee include-book) on a
 certified book because the expansion is evaluated (it is stored in the book's
 @(see certificate) for this purpose), but the expansion is merely
 @('(value-triple nil)').  To ensure that the original @('make-event') call is
 evaluated even when including the book, use @(':check-expansion t'), for
 example as follows.</p>

 @({
 (make-event (er-progn (assign my-list-of-10 (make-list 10))
                       (value '(value-triple nil)))
             :check-expansion t)
 })

 <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>Many built-in @(see state) globals revert after expansion.  If your own
 state global (like @('my-global') above) can be set during expansion, then the
 new value will persist.  But that persistence will fail for many state
 globals, specifically, those that are stored in the list,
 @('*protected-system-state-globals*').  We advise users <b>not</b> to assume
 that system state modifications, such as the state of guard-checking, will
 persist after executing a @('make-event') form; persistence depends on the
 relevant state globals not being in the list,
 @('*protected-system-state-globals*').</p>

 <p>That advice may suffice for most users.  But if you want to understand the
 point above more deeply, then consider the following example.</p>

 @({
 (make-event
  (er-progn (set-guard-checking :none) ; sets state global 'guard-checking-on
            (assign my-global (car 3))
            (value (list 'value-triple (@ my-global)))))
 })

 <p>This @('make-event') form succeeds and afterwards, the value of @('(@
 my-global)') is @('nil'), which of course is the value expected after the call
 above of @(tsee assign).  However, the value of @('(@ guard-checking-on)')
 after executing this @('make-event') form is @('t'), not @(':none').  That is
 because the symbol @('guard-checking-on') belongs to the list of symbols
 stored in the constant, @('*protected-system-state-globals*'), and thus the
 value of the state global @('guard-checking-on') is reverted to its initial
 value (which was assume here is the default, @('t')) after the @('make-event')
 form completes execution.</p>

 <p><b>Remarks on @('*Protected-system-state-globals*') for advanced
 users.</b></p>

 <ul>

 <li>The constant @('*protected-system-state-globals*') is defined to include
 all built-in state globals, <i>except</i> for those that the ACL2 implementors
 have decided can safely retain values set during @('make-event') expansion.
 If you find state globals that you would like to be added to this list of
 exceptions, please contact the ACL2 implementors.  Note for example that it
 would not be safe to allow @('guard-checking-on') as an exception, since ACL2
 relies on the persistence of this state global's value after each event
 (for explanation, see the Essay on Guard Checking in the ACL2 sources).</li>

 <li>As noted in a comment in the example above, the macro @(tsee
 set-guard-checking) sets the state global, @(''guard-checking-on').  A natural
 question is how one might know this.  For most ACL2 users (one might say,
 traditional ACL2 users), it should suffice simply not to expect system state
 modifications (like the state of guard-checking) to persist after executing a
 @('make-event') form.  For system implementors, one however needs to work with
 the ACL2 system by looking at the definition of the utility &mdash; in this
 example, @('set-guard-checking') &mdash; or at the least, get a sense of its
 expansion by using macroexpansion (for example see @(see trans1)).</li>

 </ul>

 <h3>Advanced Expansion Control</h3>

 <p>We conclude this @(see documentation) section by discussing additional
 control over @('make-event') expansion.  The discussion below is split into
 the following parts; further discussion follows.  The first three parts are
 illustrated in community book
 @('books/make-event/make-event-keywords-or-exp.lisp').</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>(4) In contexts where proofs are normally skipped (see @(see
 ld-skip-proofsp)), the expansion phase normally takes place with proofs
 skipped unless the @(':CHECK-EXPANSION') keyword is supplied a non-@('nil')
 value.  However, proofs can be made to take place unconditionally during the
 expansion phase by using an attachment, as discussed below.</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 does not
 permit nesting such as @('(:OR ev-1 (:OR ev-2 ev-3))').  That is, when an
 expansion result is @('(:OR ev-1 ev-2 ... ev-k)'), none of the @('ev-i') may
 be of the form @('(:OR ...)').  Note that it is allowed for @('ev-i') to be a
 call of @('make-event'), even one involving this special use of @(':OR').  If
 @('ev-i') is <tt>(:DO-PROOFS ev-i')</tt>, then @('ev-i'') is considered to be
 the expansion in place of @('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>

 <p>(4) Unconditionally enabling proofs during the expansion phase using an
 attachment.</p>

 <p>Proofs are normally skipped during the expansion phase unless the
 @(':CHECK-EXPANSION') keyword is supplied a non-@('nil') value.  To cause
 proofs to take place unconditionally during the expansion phase, evaluate one
 of the following two forms, as explained below.</p>

 @({
 (defattach (always-do-proofs-during-make-event-expansion
             constant-t-function-arity-0)
   :system-ok t)

 (defattach (always-do-proofs-during-make-event-expansion
             constant-all-function-arity-0)
   :system-ok t)
 })

 <p>The first of these is probably preferred in most cases, since it does not
 have any effect while evaluating an @(tsee include-book) form (more precisely,
 when @('(ld-skip-proofsp state)') is @(''include-book')).  The second removes
 that restriction.</p>

 <p>To restore the default behavior, evaluate the following.</p>

 @({
 (defattach (always-do-proofs-during-make-event-expansion
             constant-nil-function-arity-0)
   :system-ok t)
 })

 <p>(If you would like an explanation of @('defattach') in general, see @(see
 defattach).)</p>")
other
(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 to 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 brief look at how we expand @(tsee progn) and @(tsee
 encapsulate) forms.  More details are found further below (see ``Detailed
 semantics'').</p>

 <p>@('(progn ... (make-event form ...) ...)')</p>

 <p>The expansion is obtained, roughly speaking, by replacing the
 @('make-event') form by its expansion, @('exp'), except that if
 @(':check-expansion exp') is supplied explicitly, then no such replacement
 takes place.</p>

 <p>Expansion for @('(encapsulate ... (make-event form ...) ...)') is similar
 to the case for @('progn'), except that if the expansion of @('form') is
 @('exp'), then what is stored is @('(record-expansion (make-event form ...)
 exp)').  Also as for @('progn'), the exception is that when
 @(':check-expansion exp') is supplied explicitly, no such replacement takes
 place.  Here, @('record-expansion') is a macro that simply returns its second
 argument, but is used for checking redundancy of @('encapsulate') forms (see
 @(see redundant-encapsulate)).</p>

 <p>Certain ``wrappers'' around a @('make-event') are restored as the last part
 of the expansion process, in particular for @('make-event') calls that are
 inside calls of @(tsee encapsulate) or @(tsee progn), as well as in events
 processed during a book's certification, including @(see portcullis) commands
 from the certification @(see world).  For example, if you evaluate a form
 @('(local (with-prover-step-limit 100 (make-event ...)))')  where the
 @('make-event') call has expansion @('<exp>'), and then you certify a book,
 the book's @(see certificate) file will include among its portcullis commands
 the form @('(local (with-prover-step-limit 100 <exp>))').  Macroexpansion is
 performed to determine the wrappers.  The wrappers thus restored are as
 follows.</p>

 @({
 local
 skip-proofs
 with-cbd
 with-guard-checking-event
 with-output
 with-prover-step-limit
 with-prover-time-limit
 })

 <p>The discussion below references this process as the final expansion being
 ``rebuilt from'' the form.</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 shown below.  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.</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 @('(progn form1 form2 ...)') (and similarly for @(tsee
 progn!)), and at least one @('formi') has an expansion, then the expansion of
 the original form is obtained by replacing each @('formi') by its expansion
 and then rebuilding the entire @('progn') call from @('B').</p>

 <p>If @('B') is @('(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>(Optional Implementation Notes.  The latest expansion of a @(tsee
 make-event), @(tsee progn), @(tsee progn!), or @(tsee encapsulate) is
 temporarily 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').  Expansions ultimately
 show up in the world's @(tsee command) tuples; for example, immediately after
 processing a command its expansion is
 @('(access-command-tuple-last-make-event-expansion (cddr (car (w state))))').
 Top-level expansions do not include rebuilding of wrappers, although such
 wrappers are restored when constructing @(see portcullis) commands as
 discussed above.  End of Implementation Notes.)</p>

 <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,'' where each event @('ev') for which expansion took place during
 the proof pass of certification is replaced by its expansion, but with certain
 @(tsee local) events elided.</p>

 <p>Optional 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 argument</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>

 <h3>The @(':save-event-data') keyword argument</h3>

 <p>See @(see get-event-data) for relevant background on data stored for each
 event.  The association list stored in @('last-event-data') is normally
 replaced every time an event concludes (at the summary phase), and that holds
 for calls of @('make-event').  But there is the following exception: when
 @('make-event') is called with a non-@('nil') value for keyword
 @(':save-event-data'), then that association list persists from the expansion
 phase.  This is how the @(tsee thm) macro is able to populate the
 @('last-event-data') association list without having that list be smashed when
 the surrounding @('make-event') (used for implementing @('thm'))
 concludes.</p>")
other
(defxdoc make-event-example-1
  :parents (make-event)
  :short "An example use of @(tsee make-event)"
  :long "<p>Here, we develop a reasonably self-contained example that
 illustrates how to use @('make-event') to develop tools, by solving a
 challenge posed by Alessandro Coglio.  For another such example, see @(see
 make-event-example-2).</p>

 <p>The challenge is to develop a programmatic method for solving the following
 sort of problem.</p>

 <ol>

 <li>Create a @(tsee defun) form.</li>

 <li>Submit it to ACL2, obtaining a new ACL2 @(see state) whose @(see world)
 includes the function just submitted.</li>

 <li>Access various elements of this function (e.g., unnormalized body).</li>

 <li>Create and return a new @('defun') that's based on elements of the
 previous one.</li>

 <li>Submit this new defun via a @(tsee make-event), but in a state that does
 not include the previous @('defun').</li>

 </ol>

 <p>We illustrate how to do this sort of thing by specifying the ``new
 @('defun') that's based on elements of the previous one'' to be as follows:
 add the formal, @('y'), and modify the body so that @('y') is consed onto the
 old body.  Of course, this is a trivial example that could be done without
 @('make-event'); but we solve it in a way that shows how to solve any such
 problem.  For simplicity, let's not worry about the case that @('y') is
 already a formal of the existing @('defun').  Here are the main steps.</p>

 <ul>

 <li>(a) Submit the @('defun').</li>

 <li>(b) Gather information from the resulting world.  In this case, we access
 the formals and body of the definition.</li>

 <li>(c) Create the desired event.</li>

 </ul>

 <p>The following code does those three things, as explained in comments below,
 which include references to the three steps above.</p>

 @({
 (er-progn

 ; Each of the two forms below returns an error triple (see :DOC
 ; error-triple), so we can evaluate both by using er-progn, which
 ; returns the last (second) error triple.

  (defun foo (x) (cons x x)) ; (a)
  (let ((formals (formals 'foo (w state))) ; (b)
        (body (body 'foo nil (w state))))
    (value `(defun foo ,(cons 'y formals) ; (c)
              (cons y ,body)))))
 })

 <p>So far so good: we have computed an error triple @('(mv nil val state)')
 whose value component, @('val'), is the desired @('defun') form.  However,
 that leaves us in a world that includes the first @('defun') form.  For a
 solution to the original challenge (for our specific case), that must not be
 the case, and moreover the second @('defun') form should be included in the
 current world.  Fortunately, @(tsee make-event) is perfectly suited to do both
 of these things.  Consider the following form, which simply wraps
 @('make-event') around the code displayed just above.</p>

 @({
 (make-event (er-progn
              (defun foo (x) (cons x x))
              (let ((formals (formals 'foo (w state)))
                    (body (body 'foo nil (w state))))
                (value `(defun foo ,(cons 'y formals)
                          (cons y ,body))))))
 })

 <p>The expansion phase (see @(see make-event)) computes the new @('defun')
 form &mdash; the one with the extra formal and modified body &mdash; and then
 that new @('defun') form is evaluated in the original world, which does not
 include the first @('defun') form.</p>

 <p>We complete the job by making a programmatic solution, with a macro that
 expands to such a @('make-event') form.  We make it nice by inhibiting all
 output except error output.</p>

 @({
 (defmacro cons-y-onto-body (def new-name)
   `(make-event
     (with-output!
       :off :all
       :on error
       (er-progn
        ,def
        (let* ((name ',(cadr def))
               (new-name ',new-name)
               (formals (formals name (w state)))
               (body (body name nil (w state))))
          (value (list 'defun new-name (cons 'y formals)
                       (list 'cons 'y body))))))
     :on-behalf-of :quiet!))
 })

 <p>This could be improved by doing some error checking, but we leave that as
 an exercise.</p>

 <p>Below is a log, with comments added, that shows uses of the macro
 above.</p>

 @({
 ; First we call the macro successfully.  Notice that although we inhibited
 ; output during the expansion phase (using with-output!), below we see output
 ; from the resulting new defun event.

 ACL2 !>(cons-y-onto-body (defun f (x) x) new-f)

 Since NEW-F is non-recursive, its admission is trivial.  We observe
 that the type of NEW-F is described by the theorem (CONSP (NEW-F Y X)).
 We used primitive type reasoning.

 Summary
 Form:  ( DEFUN NEW-F ...)
 Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
 Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)

 Summary
 Form:  ( MAKE-EVENT (WITH-OUTPUT! :OFF ...) ...)
 Rules: NIL
 Time:  0.03 seconds (prove: 0.00, print: 0.00, other: 0.03)
  NEW-F
 ACL2 !>:pe new-f ; Check that the new definition was indeed submitted.
  L         2:x(CONS-Y-ONTO-BODY (DEFUN F # ...) NEW-F)
               
 >L             (DEFUN NEW-F (Y X) (CONS Y X))
 ACL2 !>:pe f ; Check that the old definition was NOT submitted.


 ACL2 Error in :PE:  The object F is not a logical name.  See :DOC logical-
 name.

 ; The defun below is ill-formed, so we get an error when it is submitted,
 ; during the expansion phase.  Our use of with-output! allowed error messages,
 ; so we see the error message in this case.

 ACL2 !>(cons-y-onto-body (defun g (x) (+ y y)) new-g)


 ACL2 Error in ( DEFUN G ...):  The body of G contains a free occurrence
 of the variable symbol Y.


 Summary
 Form:  ( MAKE-EVENT (WITH-OUTPUT! :OFF ...) ...)
 Rules: NIL
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)

 ACL2 Error in ( MAKE-EVENT (WITH-OUTPUT! :OFF ...) ...):  See :DOC
 failure.

 ******** FAILED ********
 ACL2 !>
 })")
other
(defxdoc make-event-example-2
  :parents (make-event)
  :short "An example use of @(tsee make-event)"
  :long "<p>Here, we develop a reasonably self-contained example that
 illustrates how to use @('make-event') to develop tools.  For another such
 example, see @(see make-event-example-1).  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-2-exercise) for a solution.</p>")
other
(defxdoc make-event-example-2-exercise
  :parents (make-event-example-2)
  :short "Solution to an exercise from @(tsee make-event-example-2)"
  :long "<p>See @(see make-event-example-2) 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-2).</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)))))))
 })")
other
(defxdoc make-event-example-3
  :parents (make-event)
  :short "Using @(tsee make-event) to define @(tsee thm)"
  :long "<p>The definition of @(tsee thm) provides a simple, yet informative,
 example use of @('make-event').  Formerly (through ACL2 Version  8.1), this
 was the definition of @('thm'), where @('thm-fn') provides an interface to the
 prover.</p>

 @({
 (defmacro thm (term &key hints otf-flg)
   (list 'thm-fn
         (list 'quote term)
         'state
         (list 'quote hints)
         (list 'quote otf-flg)))
 })

 <p>However, this version of @('thm') did not permit calls of @('thm') in @(see
 books) or @(tsee encapsulate) forms.  To remedy that deficiency, the
 definition was changed to the following; below we explain components of this
 definition.  (It has since been updated further, but that is not relevant here
 so we don't comment here on further updates.)</p>

 @({
 (defmacro thm (&whole event-form
                       term &key hints otf-flg)
   `(with-output :off summary :stack :push
      (make-event (er-progn (with-output :stack :pop
                              (thm-fn ',term
                                      state
                                      ',hints
                                      ',otf-flg
                                      ',event-form))
                            (value '(value-triple :invisible)))
                  :expansion? (value-triple :invisible)
                  :on-behalf-of :quiet!
                  :save-event-data t)))
 })

 <p>The use of @(tsee with-output) avoids printing anything about
 @('make-event') in the @(see summary) (by using @(':off summary')).  But we do
 want a summary for the prover call itself, to see the rules used, time
 elapsed, and so on.  By using the keyword argument @(':stack :push'), but then
 calling @('with-output') again with argument @(':stack :pop') before calling
 @('thm-fn'), we remove the effect of @(':off summary') before calling
 @('thm-fn').</p>

 <p>By ignoring the @('with-output') wrapper, we may view the body of the
 @('make-event') form as follows.</p>

 @({
 (er-progn (thm-fn ...)
           (value '(value-triple :invisible)))
 })

 <p>Evaluation of this call of @(tsee er-progn) causes @('thm-fn') to be run
 and, if there is no error and the proof succeeds, to return the event
 @('(value-triple :invisible)').  That event is a no-op, and it generally
 doesn't even cause a value to be printed; see @(see ld-post-eval-print).</p>

 <p>Since an error-free expansion is always @('(value-triple :invisible)'),
 that event is specified with the @(':expansion?') keyword so that the
 expansion is not stored, in particular in a book's @(see certificate) file.
 See @(see make-event).</p>

 <p>The use of @(':on-behalf-of :quiet!') avoids a needless, distracting error
 message from @('make-event') when the proof fails.</p>

 <p>The @(':save-event-data') keyword argument is a low-level implementation
 detail that we ignore here.</p>")
other
(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>")
other
(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)")
other
(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)")
other
(defxdoc make-summary-data
  :parents (clause-processor)
  :short "Return summary data from a @(see clause-processor) function"
  :long "<p>For relevant background, see @(see clause-processor).  Here we
 discuss the value @('d') and its effect in the signature [3+] shown in that
 topic:</p>

 @({
  [3+] ((CL-PROC cl hint st_1 ... st_k) => (mv erp cl-list st_i1 ... st_in d))
 })

 <p>The purpose of @('d') is to return @(see summary) information, as
 illustrated by the following (admittedly artificial) example.  Here we
 abbreviate somewhat; the full example may be found in the @(see
 community-book), @('books/clause-processors/basic-examples.lisp').</p>

 @({

 (defevaluator evl evl-list ...)

 (defun strengthen-cl2 (cl term state)
   (declare (xargs :stobjs state))
   (cond ((null term) ; then no change
          (mv nil (list cl) state nil))
         ...
         ((pseudo-termp term)
          (mv nil
              (list (cons (list 'not term)
                          cl)
                    (list term))
              state
              (make-summary-data :runes '((:rewrite car-cons)
                                          (:rewrite cdr-cons)
                                          (:rewrite car-cons))
                                 :use-names '(nth binary-append)
                                 :by-names '(nthcdr)
                                 :clause-processor-fns
                                 '(note-fact-clause-processor))))
         (t ..)))

 (defthm correctness-of-strengthen-cl2
   (implies (and (pseudo-term-listp cl)
                 (alistp a)
                 (evl (conjoin-clauses
                       (clauses-result (strengthen-cl2 cl term state)))
                      a))
            (evl (disjoin cl) a))
   :rule-classes :clause-processor)

 (defthm test-strengthen-cl2
   (equal y y)
   :hints (("Goal"
            :instructions
            ((:prove
              :hints (("Goal"
                       :clause-processor
                       (strengthen-cl2 clause '(equal x x) state)))))))
   :rule-classes nil)
 })

 <p>Evaluation of the final @('defthm') event above prints the following @(see
 summary), which illustrates how the values of the four legal keywords for
 @('make-summary-data') naturally translate to the summary, specifically, to
 the @('"Rules"') field for the @(':runes') keyword and to the
 @('"Hint-events"') field for the others.</p>

 @({
 Summary
 Form:  ( DEFTHM TEST-STRENGTHEN-CL2 ...)
 Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL)
         (:REWRITE CAR-CONS)
         (:REWRITE CDR-CONS))
 Hint-events: ((:BY NTHCDR)
               (:CLAUSE-PROCESSOR NOTE-FACT-CLAUSE-PROCESSOR)
               (:CLAUSE-PROCESSOR STRENGTHEN-CL2)
               (:USE BINARY-APPEND)
               (:USE NTH))
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
 })

 <p>Note that each keyword is optional; in particular, the form
 @('(make-summary-data)') is legal, and it specifies @('nil') for each of the
 four keywords.  Moreover, it is also legal for @('d') to be @('nil'), which is
 equivalent to @('(make-summary-data)').  Thus, if @('d') is @('nil') or
 @('(make-summary-data)') then [3+] and [3] in the documentation for @(see
 clause-processor) have the same effect: that is, there will be no visible
 effect if we change such a clause-processor function (i.e., one returning
 empty summary data) from form [3+] to form [3] by dropping the return value of
 @('d').</p>

 <p>Duplicates are allowed in the list, for each argument of
 @('make-summary-data'); no duplicates will appear in the summary.  There is
 also no need to sort elements of those lists.</p>

 <p>Finally, note that the summary information from @('d') not only goes into
 the summary, but also is incorporated when extending the @(see
 proof-supporters-alist) to record the dependencies of the completed event.</p>

 @({
 (assert-event
  (equal (sort-symbol-listp
          (car (global-val 'proof-supporters-alist (w state))))
         '(BINARY-APPEND CAR-CONS CDR-CONS
                         NOTE-FACT-CLAUSE-PROCESSOR NTH NTHCDR
                         STRENGTHEN-CL2 TEST-STRENGTHEN-CL2)))
 })")
other
(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>")
other
(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') is generally a well-formed wormhole status
 (but see below), @('code') should be @(':ENTER') or @(':SKIP'), and @('data')
 is arbitrary.  This function returns a new status with the specified entry
 code and data.  The result does not logically depend on @('whs'), but if the
 wormhole status corresponding to the given code and data is equal to @('whs'),
 then @('whs') is returned, which will save a cons.</p>

 <p><b>Warning</b>: if @('data') is large then the equality test can be slow.
 That problem is avoided by passing @('whs = nil').  For an example of this use
 of @('nil') in the ACL2 source code, see source function
 @('save-ev-fncall-guard-er').</p>")
other
(defxdoc makunbound-global
  :parents (programming-with-state acl2-built-ins)
  :short "Remove the value assigned to a global variable in @(tsee state)"
  :long "@({
  Examples:
  (makunbound-global 'y state)

  General Form:
  (makunbound-global s state)
 })

 <p>where @('s') evaluates to a symbol.</p>

 <p>This value returned is the result of modifying the ACL2 @(see state) so
 that the given symbol does not have a value.  This function thus acts as a
 no-op if the symbol does not have a value in the given state.  Also see
 related utilities @(tsee f-get-global), @(tsee f-put-global), and @(tsee
 f-boundp-global).</p>")
other
(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>")
other
(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)")
other
(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)")
other
(defxdoc maybe-flush-and-compress1
  :parents (arrays acl2-built-ins)
  :short "Compress a one-dimensional array only if necessary"
  :long "<p>The call @('(maybe-flush-and-compress1 name ar)') is equivalent to
 the first calling @('(flush-compress name)') and then @('(compress1 name
 ar)'), except that both operations are skipped (and @('ar') is returned) if
 @('ar'), which has name @('name'), is already compressed.</p>")
other
(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>")
other
(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>")
other
(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))
 })")
other
(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>")
other
(defxdoc measure
  :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,
 @('get-measure'), may be found in the @(see community-books), file
 @('std/system/get-measure.lisp').</p>")
other
(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>")
other
(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)")
other
(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
           :aokp         t/nil        ; optional (default nil)
           :commutative  t/lemma-name ; optional (default nil)
           :condition    condition    ; optional (default t (unless :invoke))
           :condition-fn condition-fn ; optional
           :forget       t/nil        ; optional (default nil)
           :hints        hints        ; optional, for verifying the
                                      ;   guards of condition-fn
           :ideal-okp    t/:warn/nil  ; optional (default nil)
           :invoke       nil/fn       ; optional (default nil)
           :memo-table-init-size size ; optional (default *mht-default-size*)
           :otf-flg      otf-flg      ; optional, for verifying the
                                      ;   guards of condition-fn
           :recursive    t/nil        ; optional (default t)
           :stats        t/nil        ; optional (default t (unless :invoke))
           :total        ;            ; see :DOC memoize-partial
           :verbose      t/nil        ; optional (default nil)
           )
 })

 <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); if it returns any @(see stobj)s; if it has been excluded by @(tsee
 never-memoize); or if it is excluded because it is ``special'' in the sense
 that it is in the @('"COMMON-LISP"') @(see package), it has no fixed output
 signature (i.e., it is in the value of the list constant
 @(`*stobjs-out-invalid*`), @(`*stobjs-out-invalid*`)), it has associated
 raw-Lisp code, or it is used in the implementation of @(see
 hons-and-memoization).  A constrained function (typically, one that is
 introduced in the signature of an @(tsee encapsulate) event) cannot be
 memoized; in that case, one may wish to memoize its caller or attachment (see
 @(see defattach)).  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 by documenting keyword parameters not discussed above.</p>

 <p>Keyword parameter @(':invoke') is @('nil') by default, but its value can be
 a symbol, @('g').  Examples may be found in @(see community-books) file
 @('demos/memoize-invoke-input.lsp'); for a tool built on this capability that
 supports evaluation using proved input-output pairs for a function, see @(see
 add-io-pairs).  The effect of @(':invoke g') is to replace every call of
 @('fn') by a call of @('g').  However, there are some restrictions.  The
 function symbol @('fn') must be in @(':logic') mode, and the symbol @('g')
 must be a @(see guard)-verified @(':')@(tsee logic)-mode function symbol with
 the same @(see signature) as that of @('fn').  There is the following proof
 obligation: there must be a theorem in the current ACL2 @(see world) stating
 the equality of calls of @('fn') and @('g') on a duplicate-free argument list;
 for example, if the formals list of @('fn') is @('(x1 ... xn)'), then the
 theorem could be @('(equal (fn x1 .... xn) (g x1 ... xn))').  If ACL2 finds no
 such theorem, it will print a @(tsee defthm) event that you may wish to
 submit.  Next we describe a potential second proof obligation, which will
 similarly be printed if it is not met.  Let @('guard-fn') be the @(see guard)
 for @('fn'), and let @('guard-g') be the result of substituting the formals of
 @('fn') for the formals of @('g') in the guard for @('g').  If @('guard-fn')
 tautologically implies @('guard-g') (for example, the two are equal or
 @('guard-g') is @(''T')), then there is no further proof obligation.
 Otherwise, there must be a theorem in the current ACL2 @(see world) of the
 form @('(implies guard-fn guard-g)').  See @(see verify-guard-implication) for
 a utility that makes it easy for you to prove such a theorem.  Finally,
 contrary to the usual defaults, the values of keyword @(':recursive'),
 @(':condition') and @(':stats') default to @('nil').  Indeed, it is an error
 to specify a non-nil value for @(':recursive').  The alternate defaults of
 @('nil') for @(':condition') and @(':stats') can avoid memoization overhead
 when one simply wishes to call @('g') in place of @('fn'); you may override
 those defaults if you actually want to save computed values and use
 @('(memsum)') to see statistics.</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>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').  Note that because most output
 is inhibited by default, you might wish to supply keyword argument @(':verbose
 t') if the event fails.</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>Note that for this handling of @(':aokp'), the computation of a value
 returned by function @(tsee apply$-userfn) or @(tsee badge-userfn) is
 considered to have used an attachment.</p>

 <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)
  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)
  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>The value of @(':verbose') is @('nil') by default, which avoids output that
 is typically distracting.  Otherwise @('verbose') should be @('t').  We can
 see the types of output that are inhibited by default by using @(':')@(tsee
 trans1) as follows follows (most output elided here); see @(see
 with-output).</p>

 @({
 ACL2 !>:trans1 (memoize 'nth :verbose nil)
  (WITH-OUTPUT
      :OFF (SUMMARY PROVE EVENT)
      :GAG-MODE NIL
      ...
 ACL2 !>
 })

 <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>")
other
(defxdoc memoize-partial
  :parents (memoize)
  :short "@(tsee Memoize) a partial version of a limited (`clocked') function"
  :long "<p>See @(see memoize) for relevant background.  Here we describe a
 utility that supports effective memoization for functions that have been
 introduced by @(tsee defun), as follows, under certain restrictions.</p>

 @({
 (defun fn-limit (x1 ... xn limit)
   (declare ...) ; optional, as usual for defun ; ;
   (if (zp limit)
       <base>
     (let ((limit (1- limit)))
       <body>)))
 })

 <p>Here @('fn-limit') represents a function symbol and @('(x1 ... xn limit)')
 denotes a non-empty list of formal parameters, where we call the final
 formal (here, shown as @('limit')) the ``limit variable''.  @('<Base>') is any
 syntactically legal expression, but @('<body>') is restricted as follows: the
 occurrences of the limit variable are exactly as the final parameter in each
 recursive call of @('fn').  More precisely, that restriction must hold after
 @('<body>') is converted to a translated term (see @(see term)).  In other
 words, the translation of @('<body>') must have the property that the limit
 variable only occurs in recursive calls, and in those calls it occurs exactly
 as the final argument and not in any other arguments.</p>

 <p>Such use of a ``limit'' argument to obtain termination is an old trick that
 pre-dates ACL2.  Such ``limited'' functions have traditionally often been
 called ``clocked'' functions.  In this documentation we refer to such a
 function as a ``total'' function, because the limit argument guarantees that
 its evaluation terminates.  We will be generating a corresponding ``partial''
 function that avoids the limit argument, and hence might not terminate &mdash;
 but when it does, it computes the desired value, and uses memoization to do
 so, which can speed up computation.</p>

 <p>We organize the rest of this topic as follows: General Form, Basic Example,
 Example with Mutual Recursion, Detailed Documentation, and Optional Technical
 Remarks.</p>

 <h3>General Form:</h3>

 @({
 (memoize-partial fn+ ; see below
                  :kwd1 val1 ... :kwdn valn)
 })

 <p>where the supplied @(':kwdi') and @('vali') are valid keywords and values
 for @(tsee memoize).  In the simplest case, @('fn+') is a symbol.  Later
 below, after providing an example, we give more complete documentation,
 including discussion of @(tsee mutual-recursion) and the general case for
 @('fn+').  None of the arguments is evaluated.</p>

 <h3>Basic Example</h3>

 <p>The following example from @(see community-book) file
 @('books/demos/memoize-partial-input.lsp') illustrates the use of @(tsee
 memoize-partial).  Consider the <a
 href='https://en.wikipedia.org/wiki/Collatz_conjecture'>Collatz
 Conjecture</a>, sometimes known as the 3n+1 problem.  For any positive integer
 @('n'), compute a new integer as @('n/2') if @('n') is even, else as
 @('3*n+1').  The Collatz conjecture states that this process eventually
 reaches @('1').  Since this is an open problem, we can't realistically hope to
 prove termination, so we may code the above algorithm by using a limit
 argument, as follows.  This function returns, unless the limit is reached, the
 number of steps required for the computation to terminate (reach 1).</p>

 @({
 (defun collatz-limit (n limit)
   (declare (xargs :guard (and (natp n)
                               (natp limit))
                   :measure (acl2-count limit)))
   (if (zp limit)
       (prog2$ (er hard? 'collatz-limit
                   "Limit exceeded!")
               0)
     (let ((limit (1- limit)))
       (if (int= n 1)
           0
         (1+ (collatz-limit (if (evenp n)
                                (floor n 2)
                              (1+ (* 3 n)))
                            limit))))))
 })

 <p>A moment's reflection suggests that if this algorithm terminates, then
 there are no cycles, so memoization from a single call will be useless.
 However, memoization can be useful if we make distinct calls.  But memoization
 might not be very useful even then, because after we save the result of a call
 @('(collatz-limit n0 limit0)'), a later call on @('n0') might be with a
 different limit, say, @('(collatz-limit n0 limit1)').  So we prefer to memoize
 using the corresponding partial function, without a limit argument.  We can do
 that as follows.</p>

 @({
 (memoize-partial collatz)
 })

 <p>Under the hood this generates, essentially, the following Common Lisp
 definition, which is to be memoized.</p>

 @({
 (defun collatz (n)
   (if (int= n 1)
       0
     (1+ (collatz (if (evenp n)
                      (floor n 2)
                    (1+ (* 3 n)))))))
 })

 <p>Since the @('limit') argument has disappeared, memoization is now more
 effective.  But how can one define @('collatz') in the ACL2 logic?  The
 @('memoize-partial') call shown above actually generates the following events,
 which define @('collatz') to capture the notion of the ``eventual stable
 value, as @('limit') goes to infinity, of @('(collatz n limit)')''.  It
 probably is not important to read these events unless one plans to reason
 about @('collatz'), and even then one might be able to complete proofs without
 reading these events.</p>

 @({
 (DEFCHOOSE COLLATZ-LIMIT-CHANGE (LARGE)
   (N LIMIT)
   (AND (NATP LARGE)
        (<= LIMIT LARGE)
        (NOT (EQUAL (COLLATZ-LIMIT N LIMIT)
                    (COLLATZ-LIMIT N LARGE)))))
 (DEFCHOOSE COLLATZ-LIMIT-STABLE (LIMIT)
   (N)
   (AND (NATP LIMIT)
        (EQUAL (COLLATZ-LIMIT N LIMIT)
               (COLLATZ-LIMIT N (COLLATZ-LIMIT-CHANGE N LIMIT)))))
 (DEFUN COLLATZ (N)
   (DECLARE (XARGS :GUARD (LET ((LIMIT 0))
                               (DECLARE (IGNORABLE LIMIT))
                               (AND (NATP N) (NATP LIMIT)))))
   (COLLATZ-LIMIT N (NFIX (COLLATZ-LIMIT-STABLE N))))
 })

 <p>The upshot is a logical definition of @('(collatz n)') as the eventual
 value (if any), as @('limit') increases without bound, of @('(collatz n
 limit)') &mdash; together with an installed Common Lisp definition that is
 actually executed and, moreover, is memoized.</p>

 <p>We note that the call @('(memoize-partial collatz)') also generates a
 @(tsee table) event as well as the form @('(MEMOIZE 'COLLATZ :TOTAL
 'COLLATZ-LIMIT)').  However, these details are best ignored by the user; we do
 not expect those events to be generated by hand, and in particular it is
 probably inadvisable to use the @(':TOTAL') keyword of @(tsee memoize) other
 than indirectly using @('memoize-partial').  Failure to heed this advice could
 make failures more difficult to debug.</p>

 <p>See @(see community-book) file @('books/demos/memoize-partial-input.lsp')
 for an application of this use of @('memoize-partial'), to compute the total
 number of steps required (without accounting for memoization) to run the
 Collatz algorithm to completion on the first @('n') positive integers.</p>

 <h3>Example with Mutual Recursion</h3>

 <p>The following example, also from @(see community-book) file
 @('books/demos/memoize-partial-input.lsp'), illustrates the use of
 @('memoize-partial') on functions that have been defined using @(tsee
 mutual-recursion).  (The suffix ``@('-bdd')'' below is intended to denote
 ``bounded'', to suggest what the ``@('-limit')'' suffix suggested in the first
 example.)</p>

 @({
 (mutual-recursion
  (defun evenlp-bdd (x bound)
    (declare (xargs :guard (natp bound)))
    (if (zp bound)
        'ouch
      (let ((bound (1- bound)))
        (if (consp x) (oddlp-bdd (cdr x) bound) t))))
  (defun oddlp-bdd (x bound)
    (declare (xargs :guard (natp bound)))
    (if (zp bound)
        'ouch
      (let ((bound (1- bound)))
        (if (consp x) (evenlp-bdd (cdr x) bound) nil)))))

 (memoize-partial ((evenlp evenlp-bdd) (oddlp oddlp-bdd)))
 })

 <p>Notice that this time the argument of @('memoize-partial') is a list of
 tuples.  Each tuple is a list with two elements: the name of the partial
 function to be defined, followed by the corresponding total (limited) function
 that has already been defined.  Indeed, the preceding example abbreviates
 @('(memoize-partial ((collatz collatz-limit)))').  Such abbreviations are
 discussed in the Detailed Documentation section below.</p>

 <p>Recall that in the first example, the @('memoize-partial') call defined
 functions @('collatz-limit-change') and @('collatz-limit-stable') using @(tsee
 defchoose), and then function @('collatz') using @(tsee defun).  In the
 present example such a trio of functions is introduced for each of the
 functions defined in the corresponding @('mutual-recursion') &mdash;
 equivalently, for each of the tuples supplied to @('memoize-partial').</p>

 @({
 (DEFCHOOSE EVENLP-BDD-CHANGE (LARGE)
   (X BOUND)
   (AND (NATP LARGE)
        (<= BOUND LARGE)
        (NOT (EQUAL (EVENLP-BDD X BOUND)
                    (EVENLP-BDD X LARGE)))))
 (DEFCHOOSE EVENLP-BDD-STABLE (BOUND)
   (X)
   (AND (NATP BOUND)
        (EQUAL (EVENLP-BDD X BOUND)
               (EVENLP-BDD X (EVENLP-BDD-CHANGE X BOUND)))))
 (DEFUN EVENLP (X)
   (DECLARE (XARGS :GUARD (LET ((BOUND 0))
                               (DECLARE (IGNORABLE BOUND))
                               (NATP BOUND))))
   (EVENLP-BDD X (NFIX (EVENLP-BDD-STABLE X))))
 (DEFCHOOSE ODDLP-BDD-CHANGE (LARGE)
   (X BOUND)
   (AND (NATP LARGE)
        (<= BOUND LARGE)
        (NOT (EQUAL (ODDLP-BDD X BOUND)
                    (ODDLP-BDD X LARGE)))))
 (DEFCHOOSE ODDLP-BDD-STABLE (BOUND)
   (X)
   (AND (NATP BOUND)
        (EQUAL (ODDLP-BDD X BOUND)
               (ODDLP-BDD X (ODDLP-BDD-CHANGE X BOUND)))))
 (DEFUN ODDLP (X)
   (DECLARE (XARGS :GUARD (LET ((BOUND 0))
                               (DECLARE (IGNORABLE BOUND))
                               (NATP BOUND))))
   (ODDLP-BDD X (NFIX (ODDLP-BDD-STABLE X))))
 })

 <p>The corresponding Common Lisp functions, to be executed for @(see
 guard)-verified calls of @('evenlp') and @('oddlp'), are defined as one might
 expect, in analogy to the Common Lisp definition in the first example.
 Moreover, they are memoized.  Here are (again, essentially) the Common Lisp
 definitions of @('evenlp') and @('oddlp').</p>

 @({
 (DEFUN EVENLP (X)
   (IF (CONSP X)
       (ODDLP (CDR X))
       T))
 (DEFUN ODDLP (X)
   (DECLARE (IGNORABLE X))
   (IF (CONSP X)
       (EVENLP (CDR X))
       NIL))
 })

 <h3>Detailed Documentation</h3>

 <p>Recall the General Form</p>

 @({
 (memoize-partial fn+ ; see below
                  :kwd1 val1 ... :kwdn valn)
 })

 <p>where the supplied @(':kwdi') and @('vali') represent keyword options to be
 used for a generated call of @(tsee memoize).  We discuss later below how
 @('fn+') specifies either a recursively-defined function symbol or a sequence
 of function symbols defined by @('mutual-recursion') &mdash; all @(see
 guard)-verified.  We call the final formal parameter, which must be the same
 for each function symbol defined in the @('mutual-recursion') case, the
 ``limit variable''.  The translated body (see @(see term) regarding the notion
 of ``translated'') of each of these function symbols must be of the following
 form, or of the corresponding form using @(tsee cond) in place of @(tsee if),
 where here @('limit') denotes the limit variable.</p>

 @({
   (if (zp limit)
       <base>
     (let ((limit (1- limit)))
       <body>))
 })

 <p>Moreover, each limit variable occurring in @('<body>') must occur as the
 final argument of a call of the defined function &mdash; in the mutual
 recursion case, of the functions defined by the @('mutual-recursion') &mdash;
 and conversely, each such call must have the limit variable as its final
 argument.</p>

 <p>Let us refer to each specified function as the ``total'' function.  A
 successful invocation admits a sequence of three definitions for each total
 function, which we call the ``changed'', ``stable'', and ``partial'' function.
 Here are those three definitions, where ``@('...')'' denotes the formals of
 the partial function (that is, the formals of the total function other than
 the final formal, which is the limit variable).  We write @('LIMIT') below to
 denote the limit variable.  Note that @('LARGE') is replaced by a fresh
 variable when necessary, to avoid duplicating an existing formal.</p>

 @({
 (DEFCHOOSE <changed> (LARGE)
   (... LIMIT)
   (AND (NATP LARGE)
        (<= LIMIT LARGE)
        (NOT (EQUAL (<total> ... LIMIT)
                    (<total> ... LARGE)))))
 (DEFCHOOSE <stable> (LIMIT)
   (...)
   (AND (NATP LIMIT)
        (EQUAL (<total> ... LIMIT)
               (<total> ... (<change> ... LIMIT)))))
 (DEFUN <partial> (...)
   (DECLARE (XARGS :GUARD (LET ((LIMIT 0))
                               (DECLARE (IGNORABLE LIMIT))
                               <guard_of_total>)))
   (<total> ... (NFIX (<stable> ...))))
 })

 <p>Under the hood, however, a Common Lisp definition is installed for
 @('<partial>') that avoids the limit variable, essentially by eliminating it
 in @('<body>') to produce a corresponding term, @('<body'>'), with the
 following result.  (Low-level details about exactly what is generated are
 discussed in the Optional Technical Remarks below, but should probably be
 ignored by most users.)</p>

 @({
 (defun <partial> (...)
   <body'>
 })

 <p>We turn now to the first argument of @('memoize-partial'), denoted @('fn+')
 above, with discussion of its legal forms and its relation to the
 other (keyword) arguments of @('memoize-partial').  The most flexible form for
 @('fn+') is a list of tuples, where each tuple is of the following form and
 the keyword arguments are optional and in any order.</p>

 @({
 (<partial> <total>
  :change <change>
  :stable <stable>
  :kwd1 val1 ... :kwdn valn)
 })

 <p>The symbols @('<partial>'), @('<total>'), @('<change>'), and @('<stable>')
 are as discussed above, and the arguments @(':kwd1 val1 ... :kwdn valn') are
 as supplied to @(tsee memoize).  There should be a single tuple in the singly
 recursive case.  In the case that the partial functions were defined by a
 @('mutual-recursion') defining functions @('f1'), ..., @('fn'), then the
 @('<partial>') components of the tuples (their @(tsee car)s) must also be
 @('f1'), ..., @('fn').</p>

 <p>The keyword/value pairs of the tuple are optional.  The default for
 @('<change>') is obtained by adding the suffix @('"-CHANGE"') to
 @('<total>'), to create a symbol in the same package as that of @('<total>');
 similarly for @('<stable>') and the suffix @('"-STABLE"').  The @('<total>')
 function is defined as described above, with an under-the-hood Common Lisp
 definition also as described above, and @(see memoize)d.  The @('memoize')
 call uses the keywords supplied in the tuple other than @(':change') and
 @(':stable').  For any @('memoize') keywords not specified in the tuple, the
 keywords specified at the top level of the @('memoize-partial') call &mdash;
 that is, the keyword arguments (if any) following the first argument (that is,
 following @('fn+')) &mdash; are also used in that generated @('memoize')
 call.</p>

 <p>There are some abbreviations allowed for @('fn+'), as follows.</p>

 <ul>

 <li>A symbol @('fn') for @('fn+') abbreviates the list @('(fn)'), which is an
 abbreviation as noted below.</li>

 <li>If @('fn+') is a list @('(t1 ... tk)'), then each @('ti') that is a
 symbol, say @('fn'), abbreviates the tuple @('(fn fn-limit)'), where
 @('fn-limit') is obtained by adding the suffix @('"-LIMIT"') to @('fn'), to
 create a symbol in the same package as that of @('fn').</li>

 </ul>

 <p>Consider our first example, @('(memoize-partial collatz)').  In this case
 @('fn+') is @('collatz').  By the first rule above, this abbreviates
 @('(collatz)'), which the second rule says is an abbreviation for @('(collatz
 collatz-limit)').  The default values are computed to treat this as the
 following tuple.</p>

 @({
 (collatz collatz-limit
          :change collatz-limit-change
          :stable collatz-limit-stable)
 })

 <p>Note that the keyword value @(':condition nil') for @('memoize') can be
 used to install executable definitions without actually saving values,
 essentially by merely profiling (except that unlike @(tsee profile) the
 recursive calls are also affected by the @('memoize') call).  See the example
 involving ``worse-than'' functions in community book
 @('books/demos/memoize-partial-input.lsp').</p>

 <p>We conclude this section by discussing restrictions pertaining to @(see
 stobj)s.  Recall that memoization is illegal (other than profiling) for
 functions that return a stobj or have the ACL2 @(see state) as an input.
 Those same restrictions apply to @('memoize-partial').  However, it is legal
 for the given (``total'') functions to have user-defined stobjs as inputs, as
 long as they are not returned.  In that case, the generated definition of the
 partial function will be made with a call of @(tsee non-exec) wrapped around
 the body.</p>

 <h3>Optional Technical Remarks.</h3>

 <p>Warning: These are technical remarks that are completely optional.</p>

 <p>Our general remark is to invite readers who want to dive below the user
 level, including implementation and foundational issues, to read the comment
 entitled ``Essay on Memoization with Partial Functions
 (Memoize-partial)'' in ACL2 source file @('other-events.lisp').</p>

 <p>Our more specific remark concerns generated Common Lisp definitions.
 Recall that in the Basic Example above, we say that the Common Lisp definition
 of @('collatz') is essentially as follows.</p>

 @({
 (defun collatz (n)
   (if (int= n 1)
       0
     (1+ (collatz (if (evenp n)
                      (floor n 2)
                    (1+ (* 3 n)))))))
 })

 <p>We say ``essentially'' because the actual Common Lisp definition of
 @('collatz') is a bit different, as follows.</p>

 @({
 (DEFUN COLLATZ (N)
   (DECLARE (IGNORABLE N))
   (FLET ((COLLATZ-LIMIT (N LIMIT)
                         (DECLARE (IGNORE LIMIT))
                         (COLLATZ N)))
         (DECLARE (INLINE COLLATZ-LIMIT))
         (LET ((LIMIT 0))
              (DECLARE (IGNORABLE LIMIT))
              (IF (INT= N 1)
                  0
                  (1+ (COLLATZ-LIMIT
                       (IF (EVENP N) (FLOOR N 2) (1+ (* 3 N)))
                       LIMIT))))))
 })

 <p>A little reflection will conclude that these two definitions are
 equivalent.  The latter, however, avoids a macroexpansion issue discussed in
 the aforementioned Essay.</p>")
other
(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>")
other
(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>")
other
(defxdoc merge-sort-lexorder
  :parents (lists acl2-built-ins)
  :short "Sort a list"
  :long "<p>The call @('(merge-sort-lexorder x)') sorts the true-list @('x')
 using a non-strict total order, @(tsee lexorder), on the ACL2 universe.</p>")
other
(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))>
 })")
other
(defxdoc meta-extract
  :parents (meta clause-processor)
  :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 term naturally
 constructed from the @('rewrite-rule') record structure @('(nth N (getpropc FN
 'lemmas nil (w state)))') if @('N') is in range, else @('*t*').
 (The ACL2 source function @('rewrite-rule-term') does this construction of a
 term from a @('rewrite-rule') record structure.  It has a guard of @('t'); a
 version that may execute more quickly but has a less trivial guard is
 @('rewrite-rule-term-exec').)  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 :linear-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 term naturally
 constructed from the @('linear-lemma') record structure @('(nth N (getpropc FN
 'linear-lemmas nil (w state)))') if @('N') is in range, else @('*t*').
 (The ACL2 source function @('linear-lemma-term') does this construction of a
 term from a @('linear-lemma') record structure.  It has a guard of @('t'); a
 version that may execute more quickly but has a less trivial guard is
 @('linear-lemma-term-exec').)  Thus, if @('FN') is a function symbol with more
 than @('N') associated linear-lemmas &mdash; ``associated'' in the sense of
 being a @(':')@(tsee linear) rule that has a max-term whose top function
 symbol is @('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 linear 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>")
other
(defxdoc meta-implicit-hypothesis
  :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 @(see 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>")
other
(defxdoc metafunction-context
  :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 @(see 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))
 })")
other
(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)")
other
(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>")
other
(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)")
other
(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>")
other
(defxdoc mixed-mode-functions
  :parents (apply$)
  :short "@(':')@(tsee logic) mode functions can @(tsee apply$) @(':')@(tsee
      program) mode functions"
  :long "<p>Because @(':')@(tsee program) mode functions can be given badges it
  is possible to @(tsee apply$) them from within @(':')@(tsee logic) mode
  functions.  Colloquially, we call such @(':logic') mode functions ``mixed
  mode,'' but that is a misnomer.  They are indisputably in @(':logic')
  mode.</p>

  <p>First, note that the only way to introduce a @(':program') mode function
  into @(':logic') mode functions is to use the quoted @(':program') mode
  function name in an argument slot of @(see ilk) @(':FN'), use the
  @(':program') mode function in a quoted @(tsee lambda) object or @(tsee
  lambda$) expression in a slot of @(see ilk) @(':FN') or use it in a quoted
  expression in a slot of ilk @(':EXPR').  We do not allow @(':program') mode
  functions to be called directly from @(':logic') mode functions.  For
  example, if @('prgm') is defined as a @(':program') mode function of one
  argument, and has been assigned a badge by @(tsee defbadge)</p>

  @({
  (defun foo (x)
    (declare (xargs :mode :logic))
    (apply$ 'prgm (list x)))
  })

  <p>is legal but</p>

  @({
  (defun foo (x)
    (declare (xargs :mode :logic))
    (prgm x))
  })

  <p>is not.</p>

  <p>Second, the presence of a @(':program') mode function in a @(':logic')
  mode function prohibits the @(':logic') mode function from being guard
  verified.</p>

  <p>Mixed-mode functions raise interesting questions for top-level evaluation
  and evaluation and rewriting during proofs.</p>

  <p>When a @(':program') mode function is @('apply$')ed, it is always done in
  @(tsee safe-mode).  In general, evaluating a @(':program') mode function at
  the top-level can cause hard Lisp errors.  For example,</p>

  @({
  (defun prgm (x) (declare (xargs :mode :program)) (car x))
  })

  <p>Then @('(prgm 23)') causes a hard Lisp error in both CCL and SBCL, but
  @('(prgm 'abc)') returns numbers in both of those Common Lisps, but they
  return different numbers.  Furthermore, there is no guarantee across all
  Common Lisps that @('(prgm 'abc)') will always return the same number
  throughout a given ACL2 session; the value could conceivably change as memory
  is allocated, compacted, garbage collected, etc., since according to the CLTL
  standard, one is not supposed to apply @('CAR') to any symbol other than
  @('NIL') but no error need be signaled.  It is likely that a CLTL
  implementation of @('CAR') just accesses memory where the @('CAR') component
  of a cons is supposed to be!</p>

  <p>We tolerate such behavior when @(':program') mode functions are directly
  called at the top-level because there are no axioms about them and we regard
  the evaluation of such programs from within the ACL2 loop as just a
  convenience to the user.</p>

  <p>But @('apply$') is a @(':logic') mode function and we must guarantee that
  when any @(':logic') mode function is evaluated functional substitutivity
  holds: identical calls must yield identical results.  That is, @('apply$')
  must behave like a <i>function</i> and not give different answers to the same
  questions over time when errors are not signaled.  We also strive to achieve
  the goal that @(':logic') mode functions never cause hard Lisp errors other
  than resource errors like stack overflow or memory exhaustion.  So when
  @('apply$') is given a badged @(':program') mode function, e.g., had we
  badged @('prgm') and then evaluated @('(apply$ 'prgm '(abc))'), it must at
  least return the same ACL2 object every time!  To achieve this end
  @('apply$') runs @(':program') mode functions in @(tsee safe-mode).
  (Safe mode does shift into raw Lisp on calls of guard verified @(':logic')
  mode functions which might be called from within the @(':program') mode
  function.  But a mixed mode function cannot be guard verified because the
  @(':program') mode functions used within it cannot be guard verified.)</p>

  <p>This means that a top-level call of a mixed mode function generally runs
  slower than a corresponding call of an otherwise identical @(':program') mode
  function.  (And, on the positive side, it means that mixed mode functions
  actually behave like <i>functions</i> while @(':program') mode ones may not!)
  The only way to speed up a mixed-mode function is to convert the
  @(':program') mode functions in it to @(':logic') mode with @(tsee
  verify-termination) and verify the guards.</p>

  <p>As for proofs, since there are no axioms about @(':program') mode
  functions, if a mixed-mode function is expanded in a proof all @(':program')
  mode functions in it are treated as though they are undefined.  In
  particular, the absence of a warrant on the @(':program') mode function
  @('prgm') means that @('(apply$ 'prgm '(abc))'), is not evaluated by the
  prover despite the fact that it is a ground term.</p>")
other
(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)")
other
(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)")
other
(defxdoc monitor
  :parents (break-rewrite)
  :short "To monitor attempted applications of certain rules by the rewriter"
  :long "<p>This function stores information about which runes should be
  monitored during rewriting and what criteria are used to invoke an
  interactive break when those runes are tried by the rewriter during a
  subsequent proof attempt.</p>

  <h3>Outline</h3>

  <ul>
  <li>Protocol for Using Monitors</li>
  <li>Example and General Forms</li>
  <li>Background on Rewriting</li>
  <li>Criteria for Breaks</li>
  <li>Example Break Conditions</li>
  <li>What If No Break Occurs?</li>
  </ul>

  <h3>Protocol for Using Monitors</h3>

  <p>When a proof fails and you expected it to succeed by applying rules you've
  proved, it can be helpful to see what happens when (if) the rewriter attempts
  to use your rules.  The @(see break-rewrite) utility allows you to monitor
  each attempt by the rewriter to use specific rules (@(see rune)s).  The basic
  protocol is that you turn on the break-rewrite utility with @(tsee brr) and
  then you use this facility, @('monitor'), to specify the rules you want to
  monitor and the criteria for entering an interactive break.
  (The variant @(tsee monitor!) is like @('monitor') but also makes sure the
  break rewrite utility is turned on.)  Then you attempt the failed proof
  again.  When a monitored rule is tried and the criteria for that rule are
  satisfied, the rewriter triggers an interactive break allowing you to query
  the environment and watch what happens.  The break is a read-eval-print
  loop (in fact it is managed by @('ld'), the same function that provides
  ACL2's top-level interactive loop).  However, it is inside a @(tsee
  wormhole), allowing you to see what happening in rewrite.  But any changes
  you make while in this break disappear when the break exits and the wormhole
  evaporates.  See @(see brr-commands) for a list of the commands that
  specifically give you access to parts of the rewriter's state.  Such breaks
  do not allow you to change the course of the rewriter or otherwise guide the
  proof attempt!  Breaks <b>do</b> allow you to abort a proof attempt, which
  you typically do when you've understood why your rule failed to apply.  If
  you're seeking an interactive proof checker see @(tsee proof-builder).  To
  learn about the interactive breaks triggered when monitored runes are tried,
  see @(see break-rewrite).</p>

  <p>The current topic deals with how to install a monitor on a rule.</p>

  <h3>Example and General Forms</h3>

  @({
  Examples:
  (monitor '(:rewrite assoc-of-app) 't)
  (monitor '(:r assoc-of-app) t)
  (monitor 'assoc-of-app t)
  (monitor '(rewrite assoc-of-app) '(:condition t :depth 2))
  (monitor '(rewrite assoc-of-app) '(:condition t :rf t :depth 2))

  Keyword Command Examples:
  :monitor assoc-of-app t
  :monitor lemma42 (:condition (equal (brr@ :target) '(F A (G A (H B))))
                    :rf t
                    :depth 2
                    :abstraction (F x (G x y))
                    :lambda t))

  General Forms:
  (monitor x criteria)
  (monitor x criteria t) ; a quiet version
  (monitor! x criteria)  ; like quiet monitor but turns on brr first
 })

 <p>where (the value of) @('x') is a @(see rune) or more generally a runic
 designator (see @(see theories)) designating one or more runes of classes
 @(':')@(tsee rewrite), @(':')@(tsee definition), @(':')@(tsee
 rewrite-quoted-constant), or @(':')@(tsee linear) and (the value of)
 @('criteria') is a &ldquo;keyword value list&rdquo; &mdash; a list of
 alternating keywords and values.  If no @(':condition') key is supplied,
 @(':condition t') is used.  If @('criteria') is some term, @('y'), it is
 treated as the keyword value list @('(:condition y)').  The following keywords
 and values are supported but the details are discussed below.</p>

 <ul>

 <li>@(':rf') &mdash; value must be @('T') or @('NIL'), defaults to
 @('NIL')</li>

 <li>@(':depth') &mdash; value must be a natural number</li>

 <li>@(':abstraction') &mdash; value must be a term and it is most often an
 abstraction of the pattern that triggers @('x') obtained by replacing some
 subterms of that pattern by new variables</li>

 <li>@(':lambda') &mdash; value must be @('t') or @('nil')</li>

 <li>@(':condition') &mdash; value must be a term, called the &ldquo;break
 condition&rdquo; which contains at most one free variable and that variable
 must be @(tsee state).  An interactive break is initiated only if the
 @(':condition') term evaluates to non-@('nil').  If not provided, the
 @(':condition') value defaults to @(''T').</li>

 </ul>

 <p>The keys @(':depth'), @(':abstraction'), and @(':lambda') are only relevant
 when the rule named by @('x') rewrites with an equivalence relation that is a
 refinement of the equivalence relation the rewriter is obligated to maintain
 on the current target (see @(see geneqv)) and the rule's &ldquo;pattern&rdquo;
 <b>does not match</b> the target.  They specify criteria under which a failed
 match is to be considered a &ldquo;near miss.&rdquo; Details are given
 below.</p>

 <p>The key @(':rf') with value @('T') indicates that breaks are to also
 occur (if the @(':condition') evaluates to non-@('nil') and) the rune's
 equivalence relation has failed to be a refinement of the equivalence relation
 the rewriter is obligated to maintain on the current target.  See @(see
 refinement-failure).  If @(':rf') is @('nil') or not provided, refinement
 failures do not trigger breaks but the other kinds of breaks may occur.</p>

 <p>Keywords other than @(':condition'), @(':rf'), @(':depth'),
 @(':abstraction'), and @(':lambda') are allowed with no constraints on their
 values.  The purpose of this allowance is so that the user who wants to attach
 his or her own function to ACL2's @(tsee brr-near-missp) predicate can pass
 information to that function.</p>

 <p>When successful, @('monitor') arranges for the rewriter to trigger an
 interactive break when any rule named by @('x') and of the above classes is
 tried, provided the @(see break-rewrite) utility has been turned on &mdash;
 using @(':')@(tsee brr)@(' t'), @(':')@(tsee monitor!), or @(see
 with-brr-data) &mdash; and the circumstances of the attempt to apply the rule
 satisfy the @('criteria') as checked by the function @(tsee brr-near-missp).
 @('Monitor') prints to the comment window a list of all the
 currently-monitored runes and their criteria and returns the error-triple
 @('(value :invisible)').  The so-called &ldquo;quiet&rdquo; versions above do
 no printing.</p>

 <p>Some @(':rewrite') rules are considered ``simple abbreviations''; see @(see
 simple).  These can be be monitored, but are only tried 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 rune from the list of monitored runes, use @(tsee
 unmonitor).  To see which runes are monitored and what their break
 criteria are, evaluate @('(')@(tsee 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 runes this is an illusion.  They
 all print @(see monitor)ed 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 runes 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 runes and
 their conditions during the course of a proof attempt without changing the
 @(see state) in which the proof is being constructed.</p>

 <p>Note: This list of monitored runes is maintained as a locally bound
 variable by break-rewrite.  For example, suppose that at the top-level of ACL2
 the list of monitored runes and their criteria is @('x').  Suppose you then
 start a proof attempt, a break-rewrite break occurs and in that break you use
 @('monitor') or @('unmonitor') to change the list of monitored runes to
 @('y').  Now suppose that you release or abort from the break and ACL2 returns
 to the top-level.  You might think the list of monitored runes is @('y') but
 in fact it is @('x').  The list is locally bound to value in the caller's
 environment each time break-rewrite is entered and thus restored to the value
 in the caller's environment when break-rewrite returns.</p>

 <h3>Background on Rewriting</h3>

 <p>Before we explain the criteria for triggering breaks we establish some
 basic terminology about the rewriter.  We start with how it applies
 @(':rewrite') rules.  The rewriter walks through a term (typically
 left-to-right, innermost first) maintaining a list of known assumptions
 represented as a @(see type-alist).  It rewrites each subterm under those
 assumptions.  The subterm the rewriter is currently considering is called the
 &ldquo;target&rdquo;.  Each @(':rewrite') rule is derived from some theorem
 essentially of the form @('(implies (and hyp1 ... hypn) (equiv lhs rhs))'),
 where the @('hypi'), @('lhs'), and @('rhs') are terms and @('equiv') is known
 @(see equivalence) relation.  The @('lhs') is always a function application
 and the rule derived from the theorem is stored in the ACL2 logical @(see
 world) under the topmost function symbol of the @('lhs').</p>

 <p>Each time the rewriter steps to a new target it retrieves all the rules
 stored under the topmost function symbol of the target and tries each rule in
 turn (provided the rule is enabled and its @('equiv') is a @(see congruence)
 relation in the current context).  To try a @(':rewrite') rule the rewriter
 first attempts to match the @('lhs') to the target.  By &ldquo;match&rdquo; we
 mean the rewriter tries to find a substitution for the variables of
 @('lhs') (consistent with the @(tsee restrict) hints governing the target)
 such that applying the substitution to the @('lhs') produces the target.  If
 the @('lhs') matches the target, the rewriter then attempts to establish the
 @('hypi') by rewriting each of them in turn, instantiating each @('hypi') with
 the substitution.  If the instance of each @('hypi') rewrites to true, we know
 &mdash; by the theorem justifying this rule &mdash; that that the instance of
 @('lhs') is equivalent to the corresponding instance of @('rhs'), but the
 instance of @('lhs') is the target.  So the rewriter is logically justified in
 replacing the occurrence of the target by the instance of @('rhs') and
 recursively rewrites that.  Heuristic considerations may prevent such a
 replacement, e.g., the instantiated @('rhs') is considered ``too
 complicated,'' a loop might be detected, etc.</p>

 <p>We can generalize and summarize this description just by saying that each
 rule has a pattern, some hypotheses, and a result.  We say the rule is
 &ldquo;about&rdquo; the topmost function symbol in the pattern.  If the
 pattern matches the target, the hypotheses are true, and heuristic
 considerations allow, we use the result.  @(':Definition') and
 @(':rewrite-quoted-constant') rules fit easily within this scheme.  But
 @(':linear') rules are a little different.  The conclusion of a @(':linear')
 rule an arithmetic inequality relating subterms, the pattern is one of those
 subterms, and the result is the entire inequality conclusion.  If the
 hypotheses are all rewritten to true, the result is instantiated and added to
 the context, telling the rewriter possibly useful information about the
 target.</p>

 <h3>Criteria for Breaks</h3>

 <p>If matching fails it is sometimes useful to see why.  How did the pattern
 and the target differ?  But since a rule about a given function symbol is
 tried every time the target has that same topmost function symbol, most rules
 fail to match much more often than they match.  Triggering a break on every
 failed match is counterproductive.  Instead, we introduce the notion of a
 &ldquo;near miss&rdquo; and allow you to set criteria that trigger breaks when
 a failed match is a near miss. There are three built-in near miss criteria,
 @(':depth'), @(':abstraction'), and @(':lambda').  We expect any given
 monitored command will probably specify only one of these three criteria,
 depending on the pattern in the rule and your judgment of what might be going
 wrong, but there is nothing preventing you from specifying multiple criteria.
 If any one of them is satisfied by a failed match a break will occur.</p>

 <ul>

 <li>@(':depth n') causes a break if the pattern of the rune fails to match the
 target but the pattern does match down to depth @('n').  For example, the
 pattern @('(F X (G X (H Y (I Z))))') fails to match the target @('(F A (G B
 C))'), but it does match to depth 2.  To check this criterion the break
 utility abstracts the pattern by copying it and replacing every subterm at
 @('n') by a new variable symbol.  The depth @('n') abstractions of
 @('(F X (G (H Y (I Z))))') for @('n')=1, 2, and 3 are shown below.

  <ul>
  <li>@('n') = 1: @('(F GENSYM0 GENSYM1)')</li>

  <li>@('n') = 2: @('(F X (G GENSYM0 GENSYM1))')</li>

  <li>@('n') = 3: @('(F X (G X (H GENSYM0 GENSYM1)))')</li>
  </ul>
 </li>

 <li>@(':abstraction apat') causes a break if the pattern of the rune fails to
 match the target but the translation of @('apat') does match the target.  This
 is useful when you want more control over the abstraction of the pattern than
 @(':depth') gives you.  For example, the depth 2 abstraction of @('(F X (G
 X (H Y (I Z))))') is @('(F X (G GENSYM0 GENSYM1))') but you may be interested
 only in breaks when @('(F X (G X GENSYM1))') matches the target, i.e., where
 the first arguments of @('F') and @('G') are the same.  If so you could
 specify the criterion @(':abstraction (F X (G X Y))') or, equivalently,
 @(':abstraction (F X (G X GENSYM1))').
 <ul></ul></li>

 <li>@(':lambda t') causes a break if the pattern of the rune fails to
 match the target but does match everywhere except on quoted @(tsee lambda)
 constants.  This is checked by replacing each quoted @('lambda') object in the
 pattern by a new variable.  This is particularly useful when your rule
 contains a @('lambda$') expression, which translates to a quoted @('lambda')
 constant, but the occurrence of that constant in the target has been
 rewritten (see @(see rewrite-lambda-object)).  See also the discussion of
 &ldquo;Normal Forms in Loop$ Bodies&rdquo; in @(see
 stating-and-proving-lemmas-about-loop$s).</li>

 </ul>

 <p>When a near miss break is caused it prints a message like this</p>

 @({
 (1 Breaking (:REWRITE LEMMA) on (F (G A B) A '(A B C D ...)):

 The pattern in this rule failed to match the target.  However, this
 is considered a NEAR MISS under the break criteria,
 (:CONDITION 'T :ABSTRACTION (F X1 X2 X3)), specified when this rule
 was monitored.
 })

 <p>The message then displays all of the near miss break criteria that were
 satisfied and then prompts you for input.  This allows you to inspect the
 pattern (via the @(tsee brr-commands) @(':lhs') or @(':max-term') depending on
 whether the monitored lemma is a @(':rewrite') rule or a @(':linear') rule.
 You can inspect the target term with the command @(':target').  The ``+''
 versions of those commands, e.g., @(':lhs+'), will print the terms without
 evisceration.  If you want more information about why the pattern of the rule
 failed to match the target, use the command @(':explain-near-miss') or its
 ``+'' version.  You may exit the break with any of the usual commands, e.g.,
 @(':ok') to continue the proof attempt (because perhaps you determined that
 the lemma was never supposed to match this particular target) or @(':a!') to
 abort back to the top-level to fix the problem (because you figured out why
 the lemma, as written, will not match the intended target).</p>

 <p>On the other hand, suppose the pattern of the rune matches the target.
 Then the break condition term, i.e., the @(':condition') criterion, is
 evaluated.  The only variable allowed in the break condition term is
 @('state'), which in the context of the break-rewrite utility is a @(tsee
 wormhole) state.  Suppose the break condition term evaluates to @('ans').  If
 @('ans') is @('nil'), no break occurs.  If @('ans') is @('t'), an interactive
 break occurs and the user is prompted for commands.  Otherwise, @('ans') is
 expected to be a true list of commands to be fed to the break, i.e., to be
 appended to @('standard-oi').  Those commands are then executed just as though
 the user typed them.  If they exit the break, the user is not prompted for
 further commands.  If they don't exit the break, the user is prompted for more
 commands.</p>

 <h3>Example Break Conditions</h3>

 <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 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 (app a b) c))
 })

 <p>will monitor @('(:rewrite assoc-of-app)') but will cause an interactive
 break only when the target term is literally @('(APP (APP A B) C)').</p>

 <p>Because break conditions are evaluated in the interaction environment, the
 user developing a break condition for a given rune can test candidate
 break conditions before installing them.  For example, suppose an
 unconditional break has been installed on a 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 monitored and will make the
 break condition be @(''(:go)').  This break condition always evaluates to 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
 &ldquo;traces&rdquo; the attempted applications of the 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!
                    :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!') the lemma is tried but
 with all runes 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 of the above
 @(':monitor') command is that the 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 runes 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>

 <p>Note: The combination of a non-trivial @(':condition') and some near-miss
 criteria can result in confusing behavior.  To get a near-miss break a target
 has to fail to match the rule's pattern but succeed in matching the near-miss
 criteria.  So the near-miss criteria is irrelevant if the target matches the
 rule. But to get a break the target must match the rule in such a way that the
 @(':condition') is satisfied.  Failure to get any breaks when you have a
 non-trivial @(':condition') and a very general near-miss criteria may mean
 targets matching the near-miss criteria also matched the rule's pattern but
 failed to satisfy your @(':condition').  Our personal preference when
 monitoring for near-misses is to use the default @(':condition') of @('t'), at
 least until we see what kind of matches are arising.</p>

 <h3>What If No Break Occurs?</h3>

 <p>Suppose @('rune') is a rune that names a rule about some function symbol
 @('fn').  What does it mean if you've installed a monitor on @('rune') with
 @('(:condition t :depth 1)') and <b>no break ever occurs</b>?  Then one of the
 following is probably true.</p>

 <ul>

 <li>the break-rewrite utility is not turned on &mdash; you should evaluate
 @('(brr t)'),</li>

 <li>@('rune') is disabled in the theory used for subgoals mentioning @('fn')
 &mdash; you should enable it either with a global @(tsee in-theory) command or
 a subgoal-specific @(':in-theory') hint (see @(see hints)),</li>

 <li>@('rune') names an abbreviation rule as discussed above &mdash; you should
 add the hint @(':DO-NOT '(PREPROCESS)') (see @(see hints)),</li>

 <li>the @(':')@(tsee hints) supplied includes a @(':hands-off') list that
 includes @('fn') &mdash; perhaps you should disable other rules about
 @('fn') (since that is presumably why you put @('fn') on the @(':hands-off')
 list in the first place) and remove @('fn') from the @(':hands-off')
 list,</li>

 <li>the only terms that the rewriter ever encountered with the topmost
 function @('fn') were within a @('HIDE'),</li>

 <li>no target with the topmost function symbol @('fn') was ever seen by
 rewrite &mdash; perhaps @('fn') was involved in the conjecture or introduced
 into the proof attempt but was eliminated by another rewrite.</li>

 </ul>

 <p>The rewriter is complicated.  There may be other ways this could
 happen!</p>")
other
(defxdoc monitor!
  :parents (break-rewrite)
  :short "A quiet combination of @(tsee monitor) and @(tsee brr)"
  :long "<p>@('Monitor!') is essentially the corresponding call of @(tsee
  monitor) preceded by @('(brr t)'), but avoiding output.  See @(see monitor)
  and see @(see brr).</p>

  <p>Note that @('monitor!') may be used in place of @('monitor') even when
  inside an interactive break from @(see break-rewrite); in that case, the
  @('brr') invocation on its behalf is essentially redundant.</p>")
other
(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)
  :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>

 <p>The list is printed to the comment window and <i>not</i> returned as the
 value @('(monitored-runes)').  The actual list is maintained in a wormhole
 managed by @(see break-rewrite).</p>

 <p>Technically, the list of monitored runes is a locally bound variable of
 break-rewrite.  The initial value of the variable is determined by its value
 in the containing scope of a call of break-rewrite.  The value may be changed
 during interactions within the break, but it reverts to its old value upon
 return from break-rewrite.  Thus if you monitor some runes, start a proof,
 adjust the monitored runes from within break-rewrite breaks in the proof
 attempt, and eventually return to the top-level, the value shown by
 @(':monitored-runes') will be the same as it was when you started the
 proof.</p>")
other
(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>")
other
(defxdoc msgp
  :parents (io acl2-built-ins)
  :short "Recognizer for a ``message''"
  :long "<p>The form @('(msgp x)') evaluates to true when @('x') evaluates
 either to a string or to a @('cons') whose @('car') is a string and whose
 @('cdr') satisfies @(tsee character-alistp).  Note that @('msgp') will always
 hold for the output of the macro @(see msg).</p>

 @(def msgp)")
other
(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>")
other
(defxdoc mutual-recursion
  :parents (events programming defun)
  :short "Define some mutually recursive functions"
  :long "<p>See @(see defun) for relevant background.</p>
 @({
  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').  Note that although one definition is
 acceptable, we focus on the case of at least two definitions, since normally
 one would not bother with @('mutual-recursion') otherwise.</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>However, for the following @(tsee xargs) declarations, listed
 alphabetically, it is illegal to specify more than one value, though it is
 legal to specify the same value more than once.</p>

 @({
 :GUARD-DEBUG
 :GUARD-SIMPLIFY
 :LOOP$-RECURSION
 :MEASURE-DEBUG
 :MODE
 :NON-EXECUTABLE
 :NORMALIZE
 :OTF-FLG
 :SPLIT-TYPES
 :VERIFY-GUARDS
 :WELL-FOUNDED-RELATION
 })

 <p>Thus, for example, you may specify @(':guard-debug t') in two different
 @('defun') forms in your @('mutual-recursion') call, in which case the @(see
 guard-debug) feature will be active; but you must not specify @(':guard-debug
 t') in one @('defun') but @(':guard-debug nil') in another.  It suffices to
 specify such a value once, as that will apply throughout analysis of the
 @('mutual-recursion') 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))).
 })")
other
(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>")
other
(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>")
other
(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 and then manipulate the values 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>")
other
(defxdoc mv-list
  :parents (mv acl2-built-ins)
  :short "Converting @(see multiple-value) result to a single-value 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 (@('nil')-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)")
other
(defxdoc mv-nth
  :parents (mv acl2-built-ins)
  :short "The nth element (zero-based) of a multiply valued expression"
  :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.
 So, if you do proofs about functions that involve @(tsee mv-let), you may see
 calls of @('mv-nth') in the prover output.  For example, the following are
 logically equivalent:</p>

 @({
  (mv-let (n1 n2)
          (mv (+ x y) (* x y))
          (- n1 n2))
 })

 @({
  (let ((var (list (+ x y) (* x y))))
    (let ((n1 (mv-nth 0 var))
          (n2 (mv-nth 1 var)))
      (- n1 n2)))
 })

 <p>Here is a similar such example involving the ACL2 @(see state).  The
 following two forms are logically equivalent, but the second is only legal in
 contexts such as theorems (and proofs) rather than function definitions, since
 it violates single-threadedness restrictions (more on this below; also see
 @(see state) and see @(see stobj)).</p>

 @({
  (mv-let (erp val state)
          (read-object ch state)
          (value (list erp val)))

  (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>@('Mv-nth') is given some special treatment by the prover.  To control that
 behavior see @(see theories-and-primitives).</p>

 <p>Finally, we elaborate on the single-threadedness issue above.  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.  The upshot is that it is
 generally best not to call @('mv-nth') directly, but rather to use @(tsee
 mv-let), which generates @('mv-nth') calls for reasoning but not for Lisp
 evaluation.  However, if you really want to use @('mv-nth') directly to access
 a multiply-valued result, then &mdash; at the cost of computational efficiency
 &mdash; you can use @(tsee 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>

 @(def mv-nth)")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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)")
other
(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)")
other
(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 !>
 })")
other
(defxdoc nested-stobjs
  :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), which notes that a stobj field can itself be a stobj, an
 array or hash-table of stobjs, or a @(see stobj-table).  The present @(see
 documentation) topic expands on that point.  However, we ignore stobj-table
 fields here; see @(see stobj-table) for such documentation.</p>

 <p>Our presentation is in five 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
 fourth section provides precise documentation for @('stobj-let').  We conclude
 by discussing the use of @('stobj-let') with abstract stobjs (see @(see
 defabsstobj)); the discussion below ignores abstract stobjs until reaching
 that section.</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'); and yet
 another, this one using @(tsee swap-stobjs) to exchange stobj fields of a
 stobj, is in @('books/demos/swap-stobj-fields.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, a field that is an array of bytes, and a field that is a
 hash table whose values are integers.</p>

 @({
    (defstobj st
      (int-field :type integer :initially 0)
      (ar-field :type (array unsigned-byte (10)) :initially 0)
      (ht-field :type (hash-table eql nil integer) :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 a second 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').  The third field descriptor is
 analogous to the second, but with a hash table instead of an array.  (See
 @(see stobj-table) for the fourth new kind of value for @(':type').)</p>

 @({
    (defstobj sub1 fld1)
    (defstobj sub2 fld2)
    (defstobj top
      (sub1-field :type sub1)
      (sub2-ar-field :type (array sub2 (10)))
      (sub2-ht-field :type (hash-table equal nil sub2)))
 })

 <p>The @(':initially') keyword is illegal for fields whose @(':type') is a
 stobj, an array of stobjs, or a hash table of stobjs (or, not further
 discussed here, a @(see stobj-table)).  For a stobj field, the initial value
 is provided by a corresponding call of the stobj creator for that stobj.  For
 a field that is 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>For a hash-table field, the @(':initially') keyword is not actually used
 for the initial hash table, which is empty.  Instead, the @(':initially')
 keyword typically determines the value returned when an accessor is applied to
 a key that is not bound &mdash; but not for a hash table with stobj values.
 In that case, a fresh copy of the indicated stobj is returned when applying
 the accessor to an unbound key.</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'), @('sub2-ar-field') is an array of child stobjs of
 type @('sub2') for parent stobj @('top'), and @('sub2-ht-field') is a hash
 table 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.</p>

 @({
  (let ((parent (cdr (assoc-eq 'parent *user-stobj-alist*))))
    (let* ((child (fld2 parent))
           (child (update-fld 4 child)))
      (mv child parent)))
 })

 <p>Then, in raw Lisp, @('(fld (fld2 (cdr (assoc-eq 'parent
 *user-stobj-alist*))))') 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 or hash table of stobjs (or a @(see stobj-table)).  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.  (Note that
 &ldquo;producer variables&rdquo; refers to a list of one or more
 variables.)</p>

 @({
    (stobj-let
     ((child (fld2 parent)))  ; bindings
     (child)                  ; producer variables
     (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 variables 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 variables 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.  Also see that book for an
 analogous example using a hash-table field in place of an array field; search
 there for ``hash tables with stobj value types''.</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)').  Each @('VAR') may
 occur only once, and to avoid aliasing, the same @('ACCESSOR') may not be
 bound more than once if at least one of the variables to which it's bound is
 among the @('PRODUCER-VARIABLES').  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 scalar (hence not array, hash-table, or
 stobj-table) field.  In the case @('(ACC I ST)'), @('ACC') is the accessor for
 an array or hash-table field and @('I') is either a symbol, a natural number,
 or a list @('(quote C)').  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 @('ACC') of @('ACCESSOR'), obtained by prepending the string
 @('"UPDATE-"') to the @(tsee symbol-name) of @('ACC') unless the name of
 @('ACC') ends in @('"-GET"') (suggesting a hash-table field access), in
 which case the implicit @('UPDATER') is obtained by replacing the suffix
 @('"-GET"') with @('"-PUT"').  Finally, @('ACCESSOR') has a @(see
 signature) specifying a return value that is either @('VAR') or is a stobj
 that is congruent to @('VAR'). (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 one of
 the expressions below, depending on whether the list
 @('PRODUCER-VARIABLES') has one member or more than one member, respectively.
 (But see below for extra code, denoted ``@('<check>')'', that may be inserted
 if there are stobj array or hash-table accesses in @('BINDINGS').)  We observe
 the following conventions.</p>

 <ul>

 <li>Let @('BINDINGS'') be the result of dropping each updater (if any) from
 @('BINDINGS'), that is, replacing each tuple @('(VAR ACCESSOR UPDATER)') in
 @('BINDINGS') by @('(VAR ACCESSOR)').</li>

 <li>Let @('STOBJ-LET-BOUND-VARIABLES') be
 the list of variables @('VAR') discussed above, that is, @('(strip-cars
 BINDINGS)').</li>

 <li>Let @('UPDATES') be 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))').</li>

 </ul>

 <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-VARIABLES
              PRODUCER
              (let* UPDATES
                CONSUMER)))
 })

 <p>Moreover, ACL2 places restrictions on the resulting expression: @('ST')
 must not occur free in @('PRODUCER') when at least one variable in
 @('STOBJ-LET-BOUND-VARIABLES') occurs in @('PRODUCER'); and every variable in
 @('STOBJ-LET-BOUND-VARIABLES') must not occur free in @('CONSUMER').  If one
 of these conditions is violated, you will see an error message saying that
 &ldquo;It is forbidden to use&rdquo; the variable where it should not
 occur free.</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).  When
 @('FORM') appears in the body of a definition then in some cases, its
 translation into logic is an expression of the form @('(PROG2$ <check>
 FORM')'), where @('FORM'') is the translation of @('FORM').  (See @(see term)
 for a discussion of translation.)  The @('<check>') expression generates an
 extra @(see guard) proof obligation, which guarantees that no aliasing occurs
 in @('BINDINGS') for two variables bound to accesses of the same stobj array
 or hash table, when at least one of the two variables is a producer variable.
 When ACL2 determines that no such aliasing is possible, for example because
 all the array or hash-table accesses use distinct numeric indices or because
 there are no producer variables, then @('FORM') does not undergo such
 replacement.  Warning: The use of @(':')@(tsee trans1) will not show this
 addition of a check.  But you can see it after admitting the definition of
 @('FN') (perhaps using @(tsee skip-proofs) if you are having difficulty
 admitting the definition), as follows.</p>

 @({
 (untranslate (body 'FN nil (w state)) nil (w state))
 })

 <h3>SECTION: Using @('stobj-let') with abstract stobjs</h3>

 <p>This section shows how an abstract stobj may be considered to have child
 stobj accessors and updaters that may be used with @('stobj-let'), in
 essentially in the same way that a child stobj of a concrete stobj may be
 accessed and updated with @('stobj-let').</p>

 <p>Below we assume familiarity with abstract stobjs; see @(see defabsstobj).
 We begin with a specification of child stobj accessor/updater pairs for
 abstract stobjs.  We then present an example.  Finally we conclude by
 discussing aspects of @('stobj-let') specific to abstract stobjs.</p>

 <h4>Child stobj accessors and updaters for abstract stobjs</h4>

 <p>The documentation for @(tsee defabsstobj) notes a function spec in the
 @(':EXPORTS') may introduce a child stobj accessor by including the keyword,
 @(':UPDATER'), whose value is the corresponding child stobj updater.  Here we
 flesh out that brief summary.</p>

 <p>An abstract stobj @('st') is considered to have a child stobj with accessor
 @('acc') and updater @('upd') if the @('defabsstobj') event introducing
 @('st') has a pair of function specs of the following form.</p>

 @({
 (acc :logic acc$a :exec acc$c :updater upd) ; and optionally, other keywords
 (upd :logic upd$a :exec upd$c)              ; and optionally, other keywords
 })

 <p>It is required that @('acc$c') is a child stobj accessor for the
 foundational stobj, @('st$c'), of @('st').  It is also required that
 @('upd$c') is the child stobj updater of @('st$c') that corresponds to
 @('acc$c').  We may call @('acc') and @('upd') a child stobj accessor/updater
 pair for @('st').  Note that @('st$c') may itself be an abstract stobj, in
 which case its exports @('acc$c') and @('upd$c') must be a child stobj
 accessor/updater pair for @('st$c').</p>

 <p>For @('acc') and @('acc$c') as above, @('acc') is considered to be a scalar
 accessor if @('acc$c') is a scalar accessor, and otherwise @('acc') is an
 array or hash-table accessor (unless it is a stobj-table accessor, discussed
 elsewhere; see @(see stobj-table)); similarly for @('upd'), which therefore is
 a scalar accessor if and only if @('acc') is a scalar accessor.</p>

 <p>A child stobj accessor/updater pair may be used in @('stobj-let') in the
 same way when the parent is an abstract stobj as when the parent is a concrete
 stobj.</p>

 <h4>Example uses of @('stobj-let') for an abstract stobj</h4>

 <p>The following basic example comes from the @(see community-book),
 @('books/system/tests/abstract-stobj-nesting/two-usuallyequal-nums-stobj-simpler.lisp'),
 which is based on a book contributed by Sol Swords.  This example introduces
 an abstract stobj with child stobj fields, and uses @('stobj-let') to read and
 write those fields.  For even simpler examples that illustrate array and
 hash-table fields, see community books @('absstobj-with-arrays.lisp') and
 @('absstobj-with-hash-tables.lisp') in the same directory as above.</p>

 <p>We start by introducing a concrete stobj with two child stobj fields, each
 of which represents a natural number, together with a ``valid bit'' that, when
 true, asserts the equality of those two numbers.</p>

 @({
 (defstobj n$ (n$val :type (integer 0 *) :initially 0))
 (defstobj n$2 (n$val$c :type (integer 0 *) :initially 0)
   :congruent-to n$)
 (defstobj two-usuallyequal-nums$c
   (uenslot1$c :type n$) ; stobj slot ;
   (uenslot2$c :type n$2) ; stobj slot ;
   (uenvalid$c :type (member t nil) :initially nil))
 })

 <p>We represent this concrete stobj abstractly using a cons structure of the
 form @('(valid slot1 . slot2)') for the valid bit and the two numbers.  Here
 is the recognizer for that abstract stobj.</p>

 @({
 (defun-nx two-usuallyequal-nums$ap (x)

 ; A two-usuallyequal-nums contains three fields (valid slot1 . slot2).  Valid
 ; is Boolean, and slot1 and slot2 are n$ stobjs that must be equal if valid is
 ; T.

   (declare (xargs :guard t))
   (and (consp x)
        (consp (cdr x))
        (let* ((valid (car x))
               (slot1 (cadr x))
               (slot2 (cddr x)))
          (and (booleanp valid)
               (n$p slot1)
               (n$p slot2)
               (implies valid
                        (equal slot1 slot2))))))
 })

 <p>The next step is to define functions in support of the abstract stobj that
 we intend to introduce.  Here is one such definition.</p>

 @({
 (defun-nx update-uenslot1$a (n$ x)
   (declare (xargs :guard (and (two-usuallyequal-nums$ap x)
                               (or (not (uenvalid$a x))
                                   (non-exec (equal (n$val n$)
                                                    (n$val (uenslot2$a x))))))
                   :stobjs n$))
   (cons (car x) (cons n$ (cddr x))))
 })

 <p>After introducing such functions we introduce our abstract stobj as
 follows (see the aforementioned book if you want details).  Notice the use of
 the @(':updater') keyword, which identifies child stobj fields of the new
 abstract stobj.  Thus, @('uenslot1') accesses a child stobj field of the
 @('two-usuallyequal-nums') stobj, and that field is updated by the specified
 @(':updater'), @('update-uenslot1'); similarly for @('uenslot2') and its
 corresponding updater, @('update-uenslot2').</p>

 @({
 (defabsstobj two-usuallyequal-nums
   :exports
   ((uenslot1 :logic uenslot1$a :exec uenslot1$c :updater update-uenslot1)
    (uenslot2 :logic uenslot2$a :exec uenslot2$c :updater update-uenslot2)
    (uenvalid :logic uenvalid$a :exec uenvalid$c)
    (update-uenslot1 :logic update-uenslot1$a :exec update-uenslot1$c)
    (update-uenslot2 :logic update-uenslot2$a :exec update-uenslot2$c)
    (update-uenvalid :logic update-uenvalid$a :exec update-uenvalid$c)))
 })

 <p>We may now use @('stobj-let') in the same way that we use it for concrete
 stobjs with child stobj fields.  That point is illustrated by the following
 definition, which accesses the numbers in the two child stobj fields.</p>

 @({
 (defun fields-of-two-usuallyequal-nums (two-usuallyequal-nums)
   (declare (xargs :stobjs two-usuallyequal-nums))
   (stobj-let
 ; bindings:
    ((n$  (uenslot1 two-usuallyequal-nums))
     (n$2 (uenslot2 two-usuallyequal-nums)))
 ; producer variables:
    (n1 n2)
 ; producer:
    (mv (n$val n$) (n$val n$2))
 ; consumer:
    (list :n n1 :n2 n2 :valid (uenvalid two-usuallyequal-nums))))
 })

 <p>Here is what we get when we we this function before updating the abstract
 stobj.</p>

 @({
 ACL2 !>(fields-of-two-usuallyequal-nums two-usuallyequal-nums)
 (:N 0 :N2 0 :VALID NIL)
 ACL2 !>
 })

 <p>We can update the abstract stobj by first setting the valid bit to nil, so
 that we can sequentially update the two child stobjs.  We say more about that
 point below.</p>

 @({
 (defun update-two-usuallyequal-nums (n two-usuallyequal-nums)
   (declare (xargs :guard (natp n)
                   :stobjs two-usuallyequal-nums))
   (let* ((two-usuallyequal-nums (update-uenvalid nil two-usuallyequal-nums)))
     (stobj-let ((n$ (uenslot1 two-usuallyequal-nums))
                 (n$2 (uenslot2 two-usuallyequal-nums)))
                (n$ n$2)
                (let* ((n$ (update-n$val n n$))
                       (n$2 (update-n$val n n$2)))
                  (mv n$ n$2))
                (update-uenvalid t two-usuallyequal-nums))))
 })

 <p>To see why we first update the valid bit to @('nil'), consider the logical
 translation of the @('stobj-let') form above.</p>

 @({
 ACL2 !>(untranslate (body 'update-two-usuallyequal-nums nil (w state))
                     nil
                     (w state))
 (LET
  ((TWO-USUALLYEQUAL-NUMS (UPDATE-UENVALID NIL TWO-USUALLYEQUAL-NUMS)))
  (LET
   ((N$ (UENSLOT1 TWO-USUALLYEQUAL-NUMS))
    (N$2 (UENSLOT2 TWO-USUALLYEQUAL-NUMS)))
   (MV-LET
    (N$ N$2)
    (LET* ((N$ (UPDATE-N$VAL N N$))
           (N$2 (UPDATE-N$VAL N N$2)))
          (LIST N$ N$2))
    (LET*
         ((TWO-USUALLYEQUAL-NUMS (UPDATE-UENSLOT1 N$ TWO-USUALLYEQUAL-NUMS))
          (TWO-USUALLYEQUAL-NUMS (UPDATE-UENSLOT2 N$2 TWO-USUALLYEQUAL-NUMS)))
         (UPDATE-UENVALID T TWO-USUALLYEQUAL-NUMS)))))
 ACL2 !>
 })

 <p>We can see that if the valid bit were @('t') before doing any updates, then
 the guard proof obligation would fail for the first child stobj update, made
 with @('update-uenslot1') (as defined above; see its guard).</p>

 <p>The update works, as shown in the log below.</p>

 @({
 ACL2 !>(update-two-usuallyequal-nums 17 two-usuallyequal-nums)
 <two-usuallyequal-nums>
 ACL2 !>(fields-of-two-usuallyequal-nums two-usuallyequal-nums)
 (:N 17 :N2 17 :VALID T)
 ACL2 !>
 })

 <h4>Aspects of @('stobj-let') specific to abstract stobjs</h4>

 <p>As suggested by the example above, @('stobj-let') operates about the same
 whether the parent stobj is a concrete stobj or an abstract stobj.  In this
 section we discuss some differences.</p>

 <p>One difference is that the only field accessors in the @('BINDINGS') are
 child stobj field accessors.  After all those are the only exported functions
 for an abstract stobj that may be considered to correspond to fields..</p>

 <p>Another difference is in the aliasing checks.  Recall that for an abstract
 stobj @('st'), each child stobj accessor has an @(':EXEC') function that is a
 child stobj accessor of the foundational stobj, @('st$c'), for @('st').  If
 @('st$c') is itself an abstract stobj then the @(':EXEC') function for
 @('st$c') is a child stobj accessor for the foundation of @('st$c'); and so
 on.  At the end of this chain we have a child stobj accessor for a concrete
 stobj, which we may call the underlying concrete child stobj accessor.  The
 aliasing checks are actually done with respect to the underlying concrete
 child stobj accessors that correspond to the accessors in the @('BINDINGS').
 After all, under the hood those concrete stobj functions are the ones that are
 actually executed on the ``live'' stobj.</p>

 <p>Another aspect of @('stobj-let') specific to abstract stobjs is how aborts
 are handled.  If an abort occurs in the middle of a @('stobj-let') that
 updates child stobjs, when the parent stobj is an abstract stobj, you may be
 put into an illegal state, with instructions for how to continue at your own
 risk.  See @(see illegal-state).</p>")
other
(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>")
other
(defxdoc newline
  :parents (io princ$)
  :short "Print a newline to a given output channel"
  :long "<p>This function is simply a wrapper around a call to @(see princ$)
  for the purpose of printing the ASCII character 0x0A, also known as a newline
  or line feed.</p>

 @(def newline)")
other
(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)")
other
(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 @(see 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 @(see summary),
 so that a @('NIL') subgoal comes quickly to your attention.</p>")
other
(defxdoc ninth
  :parents (nth acl2-built-ins)
  :short "Ninth member of the list"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(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)")
other
(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)))
 })")
other
(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 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>")
other
(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)")
other
(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 topic='@(url type-reasoning)'>type
 reasoning</see>; and</li>

 <li>the expansion of calls of a few built-in functions like @(tsee
 implies) (the full list is the value of the constant,
 @('*expandable-boot-strap-non-rec-fns*')).</li>

 </ul>

 <p>We have seen an example where <see topic='@(url type-reasoning)'>type
 reasoning</see> 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>")
other
(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>")
other
(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)")
other
(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 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>")
other
(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>")
other
(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>")
other
(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 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 @(see 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 ( THM ...):  It is unusual to :USE the formula
    of an enabled :REWRITE or :DEFINITION rule, so you may want to consider
    disabling (:REWRITE FOO) in the hint provided for Goal.  See :DOC using-
    enabled-rules.
 })

 <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>")
other
(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>")
other
(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>")
other
(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 change 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
 })")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(defxdoc |NOTE-2-5(R)|
  :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>")
other
(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>")
other
(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>")
other
(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 @('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>")
other
(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>")
other
(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 to 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>")
other
(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>")
other
(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>")
other
(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 @('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>")
other
(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>")
other
(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>Acknowledgments 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>")
other
(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>")
other
(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 bringing 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 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>")
other
(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)
 })")
other
(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 look 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 a 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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>Acknowledgments 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 @('add-raw-arity').  [Note added 2021:
 this utility has been removed and is no longer necessary.]</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>")
other
(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>")
other
(defxdoc note-2-8-bug-fixes
  :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, whom 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 probably cause a 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>")
other
(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>")
other
(defxdoc note-2-8-new-functionality
  :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 @('add-raw-arity').  [Note added 2021:
 this utility has been removed and is no longer necessary.]  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>")
other
(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>")
other
(defxdoc note-2-8-other
  :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>")
other
(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>")
other
(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>")
other
(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>")
other
(defxdoc note-2-8-system
  :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>")
other
(defxdoc note-2-9
  :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>")
other
(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>")
other
(defxdoc note-2-9-1
  :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>")
other
(defxdoc note-2-9-2
  :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 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 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>")
other
(defxdoc note-2-9-3
  :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>")
other
(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 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>")
other
(defxdoc note-2-9-4
  :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 for 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>")
other
(defxdoc note-2-9-5
  :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>")
other
(defxdoc note-3-0
  :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>")
other
(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>")
other
(defxdoc note-3-0-1
  :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 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 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>")
other
(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>")
other
(defxdoc note-3-0-2
  :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>")
other
(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>")
other
(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>")
other
(defxdoc note-3-2
  :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 generates 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 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) ...)
 })")
other
(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>")
other
(defxdoc note-3-2-1
  :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>")
other
(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>")
other
(defxdoc note-3-3
  :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 @('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 gag-mode),
 @(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>")
other
(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>")
other
(defxdoc note-3-4
  :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 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 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 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*').  [This constant was renamed
 @('*initial-program-fns-with-raw-code*') after Version  8.0.]</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 to 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>")
other
(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>")
other
(defxdoc note-3-5
  :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 @('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 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 though 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-enabledp') so
 that a result of @('t') says that one is in the experimental @('hons')
 version, while @('nil') says the opposite.</p>")
other
(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>")
other
(defxdoc note-3-6
  :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>")
other
(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>")
other
(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>")
other
(defxdoc note-4-0
  :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 is 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 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>")
other
(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>")
other
(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>")
other
(defxdoc note-4-1
  :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 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>")
other
(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>")
other
(defxdoc note-4-2
  :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)
     (declare (xargs :guard t :verify-guards nil))
     (forall (a b) (foo a b c)))
  (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 ACL2 Books web page.  [Note: This release note is
 obsolete, as it referenced the now-invalid URL,
 @('http://acl2-books.googlecode.com/').]</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>")
other
(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>")
other
(defxdoc note-4-3
  :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 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 an 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>")
other
(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>")
other
(defxdoc note-5-0
  :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$), @('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, 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>")
other
(defxdoc note-6-0
  :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>")
other
(defxdoc note-6-1
  :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.  (NOTE added after Version_8.3: The form is now @('(strip-cars
 *system-verify-guards-alist*)').)  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>")
other
(defxdoc note-6-2
  :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>")
other
(defxdoc note-6-3
  :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
 @('http://acl2-devel.googlecode.com').  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>")
other
(defxdoc note-6-4
  :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>")
other
(defxdoc note-6-5
  :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>")
other
(defxdoc note-7-0
  :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
 worst 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>

 ")
other
(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>")
other
(defxdoc note-7-1
  :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>

 ")
other
(defxdoc note-7-2
  :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 more 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/defevaluator-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>

 ")
other
(defxdoc note-7-3
  :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*').)</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*').</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,
 which 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 [formerly in the
 topic, system-development, and its subtopics; now expanded into <see
 topic='@(url developers-guide)'>the Developer's Guide</see>].  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') [after Version 8.5,
 @('xdoc-tag-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>

 ")
other
(defxdoc note-7-4
  :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>

 ")
other
(defxdoc note-8-0
  :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') 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>

 ")
other
(defxdoc note-8-1
  :parents (release-notes)
  :short "ACL2 Version  8.1 (September, 2018) 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 8.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>Note that only ACL2 system changes are listed below.  See also @(see
 note-8-1-books) for a summary of changes made to the ACL2 Community Books
 since ACL2 8.0, including the build system.  Also note that with each release,
 it is typical that the value of constant @(tsee *acl2-exports*) has been
 extended, and that 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 evaluation of @(see table) guards now allows attachments.  This is
 important for the implementation of @(tsee apply$) (see below).</p>

 <p>A new keyword argument for @(tsee defun-sk), @(':constrain'), can specify
 that the newly-introduced function is constrained rather than defined.  See
 @(see defun-sk).  Note that by constraining the function we make it possible
 to attach to it, and also to introduce it as a @(see guard)-verified function.
 We also made a minor change to @('defun-sk'), by moving the call of @(tsee
 extend-pe-table) out of the generated @(tsee encapsulate) form.</p>

 <p>(Of interest only to users of @(tsee apply$).)  When invoking @(tsee
 defwarrant) or @(tsee defun$), a so-called `@(see warrant)' is introduced.
 Warrants are now always @(see guard)-verified, with a guard of @('t').
 Moreover, warrants are now executable in the top-level loop; for example,
 after successfully processing @('(defwarrant foo)') or @('(defun$ foo ...)'),
 @('(warrant foo)') will evaluate to @('t') in the loop.  (Note: each warrant
 has an attachment, @('true-apply$-warrant'), that always returns @('t'); see
 @(see defattach).)  Thanks to Dmitry Nadezhin for requesting these
 enhancements.</p>

 <p>It is now required to include the system book
 @('projects/apply/apply-lemmas.lisp') before evaluating a call of @('defun$')
 or @(tsee defwarrant).  This requirement, which is enforced with an error
 that prints the necessary @(tsee include-book) form, avoids stack overflows
 that could occur when that book is not included.</p>

 <p>When performing @(tsee make-event) expansion under a surrounding @(see
 local) context, it is no longer illegal to set the @(see
 acl2-defaults-table).  For example, the following event formerly caused an
 error but is now legal.</p>

 @({
 (local (make-event (er-progn (set-ignore-ok t)
                              (defun foo (x) x)
                              (value `(value-triple ,(length (w state)))))))
 })

 <p>Information printed when giving @(':use') @(see hints) has been improved
 for the case that a @(see lemma-instance) is a @(':')@(tsee
 termination-theorem) or a @(':')@(tsee guard-theorem).  Formerly, only the
 name was shown in the `@('Hint-events')' @(see summary) and in the proof
 output; now, one will see ``names'' of the form @('(:termination-theorem
 NAME)') and @('(:guard-theorem NAME)').</p>

 <p>We improved redundancy checking for @(tsee defun) forms so that it is not
 sensitive to whether @(tsee state) has a @(':stobjs') declaration.</p>

 <p>The @(see warnings) for weak @(see type-prescription) rules have been
 eliminated.  These warnings were issued when a rule was insufficient to prove
 itself by @(see type-set) reasoning, but it seems more appropriate to
 parse the formula into a type-prescription rule before applying that check
 (for example, expanding away @(see guard-holders), which was already done, and
 beta reducing lambda applications, which was not).  Then the chance of not
 proving the result seems remote.  Thanks to Keshav Kini for an example and a
 conversation leading to this improvement.</p>

 <p>The @(see checksum) computation that can support certifying or including
 @(see books) &mdash; which is not used by default, but see @(see book-hash)
 for how to enable it &mdash; has been improved.  Specifically, at least one of
 the @(see community-books) (namely, @('books/centaur/aignet/rwlib.lisp'))
 formerly caused a stack overflow (with host Lisp SBCL, at least) before making
 this change.  (Technical note: the change is to avoid memoization for calls of
 @('fchecksum-obj') with stack depth exceeding
 @(`*fchecksum-obj-stack-bound-init*`).)  Thanks to Keshav Kini for reporting
 this issue and for related helpful communications.</p>

 <p>When a @(see break-rewrite) command such as @(':eval') or @(':go') shows
 that a rule fails because a @(see backchain-limit) is exceeded, more
 information is printed than before.  Now, the responsible rule(s) or global
 backchain-limit is indicated.  Thanks to Alessandro Coglio and Eric Smith for
 requesting this enhancement.</p>

 <p>The fancy string reader now accepts a string with three string quotes
 followed by a closing curly brace.  See @(see fancy-string-reader), in
 particular the final paragraph.  Thanks to Sol Swords for contributing this
 enhancement.</p>

 <p>The ACL2 @(tsee untranslate) function, which converts the internal
 representation of @(see term)s to user-level syntax, can now return calls of
 @(tsee mbe), @(tsee mbt), @(tsee ec-call), @(tsee cw), @(tsee time$), and
 @(tsee mv-let).  Thanks to Alessandro Coglio, Eric Smith, and Stephen Westfold
 for discussions leading to some of these changes.  Such terms rarely occur in
 practice because definitional bodies are stored with calls of @(see
 guard-holders) and @('cw') expanded.  However, here is an example of how they
 could arise.  First consider the following definition.</p>

 @({
 (defun g (n)
   (declare (xargs :normalize nil))
   (ec-call (natp n)))
 })

 <p>Here is a log before the change.</p>

 @({
 ACL2 !>(verify (equal (g x) yyy))
 ->: 1
 ->: p
 (G X)
 ->: x-dumb
 ->: p
 (LET ((N X)) (EC-CALL1 NIL (NATP N)))
 ->:
 })

 <p>After the change, the log instead ends as follows.</p>

 @({
 ->: p
 (LET ((N X)) (EC-CALL (NATP N)))
 ->:
 })

 <p>It is now illegal by default to attach to built-in functions.  To overcome
 this default behavior, see @(see defattach-system).</p>

 <p>Improvements have been made to functions in the @(tsee fmt) family,
 including for example @(tsee fms), @(tsee fmt-to-string), and @(tsee cw).
 (Also see discussion of @(tsee fmx-cw) under ``New Features,'' below.)</p>

 <ul>

 <li>Many @(see guard)s have been strengthened, for example to imply that the
 @('alist') argument must satisfy @(tsee character-alistp).  Thanks to Eric
 Smith for pointing out that an expression like @('(fmt-to-string "~x0" 3)')
 could cause a raw Lisp error (rather than causing a guard violation).</li>

 <li>Eliminated raw Lisp errors from ill-formed calls.  Thanks to Jared Davis
 for pointing out this problem in 2010 (!) with the example @('(cw "Bad:
 ~&0.~%" 5)'), and for Eric Smith for prodding us much more recently with the
 example @('(cw "~&0" 'x)').</li>

 <li>The utility @(tsee fmx) no longer prints an initial newline.  Of course, a
 call @('(fmx "<some-string>" ...)') can be modified to generate an initial
 newline (thus providing the former behavior) by adding the newline
 tilde-directive, @('"~%"'), that is, @('(fmx "~%<some-string>"
 ...)').</li>

 </ul>

 <p>The previously-undocumented built-in-function, @(tsee packn), now has a
 slightly different behavior.  Formerly, it always returned a symbol in the
 @('"ACL2"') package.  Now, the package of the symbol returned is the package
 of the first symbol in @('lst') whose package is not @('"COMMON-LISP"') if
 any, else @('"ACL2"').  Thanks to Keshav Kini for suggesting this change and
 providing its implementation.</p>

 <p>The @(see guard) on @(tsee apply$) (also the guard on @('apply$-lambda'))
 has been strengthened to require that a @(see lambda) be applied to the
 correct number of arguments.  The under-the-hood implementation for applying
 lambdas has been made slightly more efficient as a result, though that
 improvement may usually be trivial.  Perhaps more important is that guard
 verification may now catch bugs in the application of lambdas that were missed
 previously.</p>

 <p>The @(':dir') argument to @(tsee ld) was previously ignored when the first
 argument of the call of @('ld') is not a string.  Now, that is an error.  If
 you get this error, just remove the (previously ignored) @(':dir')
 argument.</p>

 <p>The function @(tsee magic-ev-fncall) sometimes printed a message in the
 error case in addition to returning that message.  It now only returns that
 message.  Thanks to Sol Swords for bringing to our attention that
 certification of a community book,
 @('books/projects/x86isa/proofs/popcount/popcount.lisp'), was printing a
 warning about @('"Meta-level function Problem"') for thousands of lines.</p>

 <p>The definition of @(tsee msgp) has been strengthened to require that for a
 @('cons') pair, the @('cdr') must satisfy @(tsee character-alistp).</p>

 <p>The @(see proof-builder) command, @('quiet!'), now inhibits all output
 except @('error') output (and that too, if already inhibited).</p>

 <p>Warnings have been modified that are labeled ``[Non-rec]'', generated for
 rules with problematic occurrences of non-recursive function symbols.  Now
 they take into account rules of class @(':')@(tsee definition).  Thanks to
 Mihir Mehta for bringing this issue to our attention.</p>

 <p>It is no longer required to specify @(':install-body nil') in a @(see
 definition) rule when the function symbol is a member of the value of the
 constant @('*definition-minimal-theory*').  Thanks to Eric Smith for pointing
 out that the utility, @(tsee install-not-normalized), was failing on, for
 example, @(tsee eq).  This change fixes that problem.  Technical note for
 system hackers only: Because of this change, the value of @('(body fn t
 wrld)') is no longer guaranteed to get the original definition of @('fn') when
 fn is in @('*definition-minimal-theory*'); for that purpose use the new
 utility, @('bbody').</p>

 <p>Many error messages now show variables according to order of appearance,
 where formerly the order was reversed.  Thanks to Eric Smith for supplying an
 example of a top-level form, @('+ a b c'), for which the error message
 reported variables in reverse order: ``Global variables, such as C, B and A,
 are not allowed.''  The message now says ``A, B, and C'' instead of ``C, B and
 A.''</p>

 <p>For @(tsee value-triple), the keyword argument @(':on-skip-proofs')
 provides new behavior if it is given the value, @(':interactive').  In that
 case, evaluation is still done under a call of @(tsee skip-proofs), as when
 the value of @(':on-skip-proofs') is @('t'); but evaluation is skipped when
 the reason proofs are being skipped is only that a book is being included or
 the second pass is being made through an @(tsee encapsulate).  Thanks to Eric
 Smith for requesting this feature.</p>

 <p>Both @(tsee fmt-to-comment-window) and @('fmt-to-comment-window!') have an
 extra argument, @('print-base-radix'), which is the same as the first argument
 to the new utilities, @(tsee cw-print-base-radix) and @(tsee
 cw-print-base-radix!) (see below).</p>

 <p>The undocumented constants @('*primitive-program-fns-with-raw-code*'),
 @('*primitive-logic-fns-with-raw-code*'), and
 @('*primitive-macros-with-raw-code*') have been renamed respectively to
 @('*initial-program-fns-with-raw-code*'),
 @('*initial-logic-fns-with-raw-code*'), and
 @('*initial-macros-with-raw-code*').  Thanks to Alessandro Coglio for
 suggesting these improved names.</p>

 <p>The @(tsee save-exec) utility now utilizes a relative pathname in the
 @('saved_acl2') script, which can allow it and a corresponding image file to
 be moved, even across filesystems &mdash; though if there is an image file,
 then probably the Lisp executable must have the same pathname even after the
 move.  Thanks to Eric Smith for suggesting this capability and providing a
 hint for how to implement it, to Sol Swords for pointing out a limitation of
 the initial implementation, and to <a
 href='https://serverfault.com/questions/40144/how-can-i-retrieve-the-absolute-filename-in-a-shell-script-on-mac-os-x'>this
 website</a> for making that solution robust.</p>

 <p>The @(tsee defevaluator) macro, and more generally the notion of evaluator,
 have been changed to include two new @(see constraint)s inserted after
 constraints 0 through 5.  The new constraints are as follows, where @('<ev>')
 refers to the evaluator.</p>

 @({
 (IMPLIES (AND (NOT (CONSP X)) (NOT (SYMBOLP X)))
          (EQUAL (<ev> X A) NIL))
 (IMPLIES (AND (CONSP X) (NOT (CONSP (CAR X))) (NOT (SYMBOLP (CAR X))))
          (EQUAL (<ev> X A) NIL))
 })

 <p>These new constraints generated by @(tsee defevaluator) are named
 @('<ev>-CONSTRAINT-6') and @('<ev>-CONSTRAINT-7')
 unless the keyword argument @(':namedp t') is supplied,
 in which case they are named @('<ev>-OF-NONSYMBOL-ATOM') and
 @('<ev>-OF-BAD-FNCALL').  Thus by default (or if
 @(':namedp') is @('nil')), this change increases by one the indices on
 constraints for the specified function symbols, because they start at 8
 instead of 6 &mdash; @('<ev>-CONSTRAINT-8'), @('<ev>-CONSTRAINT-9'), and so
 on.  Note that if you use functional instantiation to prove a theorem about
 one evaluator given a theorem about another evaluator, you'll need to enable
 the new rules (i.e., @('ev-constraint-6') and @('ev-constraint-7')
 or, if you use option @(':namedp t'),
 @('ev-of-nonsymbol-atom') and @('ev-of-bad-fncall')).
 Thanks to Sol Swords for both suggesting and
 implementing this extension.</p>

 <p>@(tsee Let)-expressions are no longer eliminated from right-hand sides of
 @(see rewrite) rules.  See @(see rewrite).  This change improves efficiency of
 the rewriter in some cases, by retaining subexpressions shared on the
 right-hand side as the rewrite rule is applied.  Thanks to Eric Smith for
 requesting this change.</p>

 <p>It was possible to declare a function symbol to be @(see untouchable) and
 yet still execute it using @(tsee apply$), thus violating the spirit of
 untouchables.  That is no longer allowed.  Here is an example of such
 execution that was formerly permitted, but is no longer.</p>

 @({
 (include-book "projects/apply/apply-lemmas" :dir :system)
 (defun$ f (x) (declare (xargs :guard t)) (cons x x))
 (push-untouchable f t)
 (apply$ 'f '(3))
 })

 <h3>New Features</h3>

 <p>The @(see summary) now shows, by default, the list of doublets @('(f g)')
 for which @('f') is a system function with attachment @('g') (see @(see
 defattach)), when @('g') differs from the initial attachment to @('f').</p>

 <p>(Warning: The following describes advanced features that can likely be
 ignored by most users.  They are available using the new utility, @(tsee
 defattach-system).)  Three new system-level functions may be given
 attachments: @('remove-trivial-equivalences-enabled-p'),
 @('assume-true-false-aggressive-p'), and @('rewrite-if-avoid-swap').  (Thanks
 to Eric Smith for suggesting these, and to him and Alessandro Coglio for
 helpful discussions.)  By default, these have the attachments
 @('constant-t-function-arity-0'), @('constant-nil-function-arity-0'), and
 @('constant-nil-function-arity-0'), respectively, which provide the existing
 system behavior.  But these attachments may be changed by the user.</p>

 <ul>

 <li>@('Remove-trivial-equivalences-enabled-p') may receive the attachment
 @('constant-nil-function-arity-0') to avoid the
 @('remove-trivial-equivalences') heuristic, which substitutes the equality (or
 even equivalence) of a variable to a term into the rest of the
 goal.  (However, perhaps similar heuristics will still be used, for example as
 part of the @(see tau-system).)</li>

 <li>@('Assume-true-false-aggressive-p') may receive the attachment
 @('constant-t-function-arity-0') to strengthen the rewriter's use of the @(see
 type-alist) when diving into @('if') terms.  A common use is to rewrite what
 amounts to @('(if (or test1 test2) (if test1 _ x) _)'); then the @(see
 type-alist) will note that @('test2') is true when rewriting @('x').  This
 change may slow down ACL2 considerably in some cases, and should rarely if
 ever be necessary when calling the prover; but it can be useful in
 applications that call the rewriter directly.</li>

 <li>@('Rewrite-if-avoid-swap') may receive the attachment
 @('constant-t-function-arity-0') to cause the rewriter &mdash; specifically,
 source function @('rewrite-if') &mdash; to avoid swapping true and false
 branches of a call of @('IF'), which could formerly happen when the test is a
 call of @('NOT').</li>

 </ul>

 <p>When the environment variable @('ACL2_CUSTOMIZATION_QUIET') is set and not
 @('""'), there will generally be no output from ACL2 customization.  A
 special value of @('"all"') for this variable will cause continued minimal
 output after startup.  See @(see acl2-customization).</p>

 <p>New utilities, @(tsee fmx-cw) and @(tsee fmx!-cw), are essentially the same
 as @(tsee cw) and @(tsee cw!) (respectively), except that @('fmx-cw') and
 @('fmx!-cw') are well-@(see guard)ed, which can catch errors in the use of
 tilde-directives.  Thanks to Eric Smith for requesting such a capability.  For
 example:</p>

 @({
 ACL2 !>(fmx-cw "Hello ~s0." '(world))


 ACL2 Error in TOP-LEVEL:  Guard violation for FMX-CW-FN:
 Illegal Fmt Syntax.  The tilde-s directive at position 6 of the string
 below is illegal because its variable evaluated to (WORLD), which is
 not a symbol, a string, or a number.

 "Hello ~s0."

 ACL2 !>
 })

 <p>New utilities, @(tsee cw-print-base-radix) and @(tsee
 cw-print-base-radix!), are like @(tsee cw) and @(tsee cw!), respectively,
 except for an additional argument that specifies the print-base and,
 optionally, the print-radix.  Thanks to Eric Smith for requesting @(tsee
 cw-print-base-radix).</p>

 <p>A new event macro, @(tsee set-in-theory-redundant-okp), allows @(tsee
 in-theory) events to be @(see redundant), which prevents @(tsee defund) and
 @(tsee defthmd) @(see events) from laying down @(tsee command) markers (as
 seen, for example, using @(':')@(tsee pbt)).  Thanks to Eric Smith for asking
 for a way for @('in-theory') events to be redundant.</p>

 <h3>Heuristic and Efficiency Improvements</h3>

 <p>The implementation of @(see wormhole)s has been tweaked to avoid an
 efficiency problem.  In the old implementation, an update to the wormhole
 status was avoided in the case of equal old and new status values.  That
 update avoided some consing, but the equality test could be very slow; indeed,
 @(':')@(tsee print-gv) could be slow because of its use of wormholes.  The new
 wormhole implementation &mdash; specifically, the new raw Lisp implementation
 of @(tsee wormhole-eval) &mdash; avoids that equality test, and also can avoid
 consing by its use of destructive operations.  That fixes one reason
 @(':print-gv') could be slow; a second change, made to the implementation of
 @(':print-gv'), is to pass @('nil') as the wormhole-status (@('whs')) argument
 of @('make-wormhole-status').  See @(see make-wormhole-status) for a
 discussion of how that use of @('nil') can avoid an expensive equality
 test.  Thanks to Alessandro Coglio and Eric Smith for sending an example that
 illustrated the problem.</p>

 <p>The following improvements have been made for evaluating calls of the form
 @('(apply$ '(lambda ...) ...)').</p>

 <ul>

 <li>An optimization had failed to be fully in place, causing such calls to run
 slowly.  That optimization compiles and caches ``tame compliant'' lambdas:
 lambda forms whose @(see guard)s are verified by the @(see tau-system) and
 that are <i>tame</i> (see @(see apply$)).  The optimization had been used in
 the unadvertised use of ``The Rubric'' prior to the release of ACL2 Version
 8.0.  Warnings about non-tame-compliant lambdas will now appear when
 appropriate, as had been the case in Version  7.4.</li>

 <li>The optimization above has been improved so that instead of three cache
 lines, there is an efficient implementation using 1000 cache lines.  That is
 probably many more than are needed, but the large size is harmless.  The
 additional cache lines dramatically improve speed when more than three lambdas
 are actively being applied; see @(see community-books) file
 @('books/system/tests/apply-timings.lisp').</li>

 <li>ACL2 no longer causes an error when the cache is in an inconsistent
 state; instead, the cache is suitably reset quietly.</li>

 </ul>

 <p>Rewriting of calls of @(tsee implies) has been optimized in the cases that
 the rewritten arguments are equal or at least one is a constant.  Thanks to
 Eric Smith for pointing out an incompleteness in the rewriting of @('implies')
 calls.</p>

 <p>The algorithm has been tweaked for generating a @(see type-prescription)
 rule to store for a given definition, so that the rule is sometimes stronger
 than was previously the case.</p>

 <h3>Bug Fixes</h3>

 <p>There was a soundness bug in the automatic functional instantiation that
 can be applied for a @(':termination-theorem') @(see lemma-instance).  Thanks
 to Eric Smith for sending an example to illustrate this bug, for suggesting
 its cause, and for permission to include that example in a comment in the ACL2
 sources definition of the constant, @('*non-instantiable-primitives*').</p>

 <p>Bugs have been fixed in the @(see tau-system) that caused unsoundness
 (going all the way back through Version  6.0, released December, 2012).  The
 problem was with conversion of a non-strict inequality with 0 to a strict
 inequality when the quantity is known not to be 0; for example, @('(<= x 0)')
 was converted to @('(< x 0)') when @('x') was known to be non-zero.  But of
 course, this conversion is only valid when @('x') is known to be a number.
 Thanks to Yan Peng for sending an example that illustrates the bug, which in
 its essence was the ability of ACL2 to prove this formula, which for example
 is false when @('x = t'): @('(or (< x 0) (= x 0) (> x 0))').  If you encounter
 a failure in a proof that formerly succeeded, the fix might be to add a call
 of @(tsee acl2-numberp) to the hypotheses of your theorem.</p>

 <p>Fixed two bugs in @(tsee apply$): we now @(tsee disable) the @(see
 executable-counterpart) of @('good-bye-fn') to prevent quitting ACL2 entirely
 during a proof, and we avoid the error ``ACL2 cannot ev the call of
 non-executable function ANCESTORS-CHECK...'' by allowing attachments to be
 used when checking table guards (as discussed above).  Thanks to Dmitry
 Nadezhin for sending replayable examples that exhibited these bugs.</p>

 <p>Fixed @(see guard)s for functions @(tsee enabled-runep), @(tsee
 enabled-numep), @('disabledp-fn'), and @('disabledp-fn-lst'), thus eliminating
 bogus guard violations.  Thanks to Alessandro Coglio and Eric Smith for
 sending an example that illustrated the bug for @('enabled-runep').  Technical
 note: this fix was made by replacing calls of @('bounded-nat-alistp') (which
 is no longer defined) by calls of @('nat-alistp') (which is newly defined).
 We also made a corresponding tweak to the definition of
 @('enabled-numep').</p>

 <p>Warnings labeled with ``Double-rewrite'' failed to take into account
 patterned @(see congruence) rules.  This has been fixed.  Thanks to Mihir
 Mehta for pointing out the problem with a helpful example.</p>

 <p>It is now possible, once again, to @(see monitor) rules of class
 @(':')@(tsee linear).  This capability has (accidentally) been unavailable
 since Version 7.4.  Thanks to Dmitry Nadezhin for reporting the bug with a
 helpful example.</p>

 <p>It was possible for users to change the attachments to built-in functions
 @('badge-userfn') and @('apply$-userfn'), which support the implementation of
 @(tsee apply$).  This is now prevented.</p>

 <p>For @(tsee defequiv), a @(':doc') keyword argument was allegedly (in the
 documentation) supported but caused an ugly error.  The @(':doc') keyword
 argument is now fully eliminated.  Thanks to Eric Smith for pointing out this
 issue.</p>

 <p>Fixed @(':')@(tsee pso) and related utilities @(':')@(tsee pso!),
 @(':')@(tsee psof), and @(':')@(tsee psog), to avoid printing some error
 messages.  Thanks to Keshav Kini for sending us an example to bring this bug
 to our attention.  Also tweaked these utilities to avoid accumulating later
 event failure messages into the saved output for a previous proof attempt, and
 to avoid some bogus output when invoked before the first proof attempt of the
 session.</p>

 <p>When an invocation of @(tsee defthmd) resulted in a macroexpansion error,
 the failure did not cause an error message to be printed.  This has been
 fixed.  Related tweaks improve error reporting, including a clearer error
 message when attempting to supply @(':rule-classes nil') with @('defthmd').
 Thanks to Keshav Kini for reporting these issues.</p>

 <p>When @(tsee defattach) was provided the argument @(':skip-checks nil'), a
 hard error was signaled.  This has been fixed.</p>

 <p>The @(tsee case-match) macro did not properly handle the @('!sym')
 construct when the symbol, @('!sym'), is not in the @('"ACL2"') package.
 This has been fixed.  Thanks to Alessandro Coglio for reporting this bug.</p>

 <p>Fixed handling of some guard violation error messages for built-in
 functions.  For example, the form @('(apply$-lambda 3 nil)') produces a guard
 violation, but before this fix, the error message reported an implementation
 error.</p>

 <p>Fixed the @(':')@(tsee puff) command to avoid certain errors involving
 @(see local) @(see events).</p>

 <p>Redundancy notes could be seen during @(tsee include-book) while loading
 the compiled file for a book.  These notes (along with, perhaps, some other
 output) have been eliminated.  Thanks to Eric Smith for pointing us to this
 problem with a reproducible example.</p>

 <p>We eliminated an obscure hard error mentioning the source function
 @('assume-true-false-if'), which could occur in the middle of a proof.  Thanks
 to Dave Greve for pointing out this problem by sending us an illustrative
 example that we could run.</p>

 <p>It was possible to get a raw Lisp error from ill-formed calls of @(tsee
 ec-call) not intended for execution, for example, @('(defun foo (x) (non-exec
 (ec-call x)))').  This has been fixed.</p>

 <p>Certain syntactic requirements are normally applied to function bodies but
 not to theorems.  However, these were being applied under calls of @(tsee
 flet).  Consider the following example.</p>

 @({
 (thm
  (flet ((foo (x) (car x)))
    (foo (mv-nth 1 (mv x x)))))
 })

 <p>This was rejected with an error: ``The expected number of return values for
 (MV X X) is 1 but the actual number of return values is 2.''  This has been
 fixed.  Thanks to Eric Smith for bringing this problem to our attention.</p>

 <p>A bug has been fixed in the logical definition of the function,
 @('read-file-into-string2'), which supports the macro, @(tsee
 read-file-into-string).  Thanks to Keshav Kini for finding this bug and to
 Mihir Mehta for a query leading to Keshav's investigation.</p>

 <p>The previous release was supposed to include a new utility, @(tsee
 checkpoint-summary-limit), but that was missing.  Thanks to Keshav Kini for
 pointing this out (and supplying the expected implementation).</p>

 <p>Fixed a bug in the guard for built-in function @('warning1-cw'), which
 could be seen for example by evaluating the form @('(warning$-cw 'my-ctx
 "The :REWRITE rule ~x0 loops forever." 'foo)').  Thanks to Keshav Kini for
 bringing this issue to our attention.</p>

 <p>The definitions of the macros @(tsee logand), @(tsee logior), @(tsee
 logxor), and @(tsee logeqv) were such that when any of these was applied to a
 single argument, the expansion was simply that argument.  For example,
 @('(logand (foo a))') expanded to @('(foo a)').  These definitions failed to
 reflect the fact that in Common Lisp, an error may be signaled if that single
 argument does not evaluate to an integer.  For example, the following
 definition was admitted: @('(defun f (x) (declare (xargs :guard t)) (logand
 x))'); yet a raw Lisp error was signaled when attempting to evaluate @('(f
 'x)'), in ACL2 built on Allegro Common Lisp.  This bug has been fixed: now,
 when any of these four macros is applied to a single argument, @('a'), the
 expansion is @('(the integer a)').  Thanks to Eric Smith for bringing this bug
 to our attention.</p>

 <p>Fixed @(':')@(tsee args) to avoid hard ACL2 error when applied to @('IF')
 and to provide a clearer error message for Common Lisp functions not in ACL2.
 Thanks to Eric McCarthy for sending examples to point out these issues.</p>

 <p>A bug has been fixed that could cause an error when processing a legal
 @(tsee flet) form, because the processing of a binding could interfere
 inappropriately with the processing of a subsequent binding, as in the
 following example.</p>

 @({
 (defun f (x) x)
 (flet ((f (x) (cons x x))
        (g (x) (f x))) ; processed with bad binding of stobjs-out for f
   (g 3))
 })

 <p>Fixed an error message saying that ``It is illegal for supporters of
 DEFAXIOM events to receive attachments'' that failed during printing.  Thanks
 to Nathan Guermond for sending an example to point out this bug.</p>

 <h3>Changes at the System Level</h3>

 <p>Fixed the use of `@('<a href='URL'>...</a>')' so that if @('URL') has the
 ampersand character in it, all will be well for both the web-based manual and
 text-based rendering (as when @(':')@(tsee doc) is used at the terminal or
 @(tsee acl2-doc) is used) provided that character is written as @('&amp;') in
 the documentation string.  Previously, the web-based manual could fail to
 display the page for @('&') in the documentation string, while with @('&amp;')
 used, the web-based manual could display the page but the text-based rendering
 showed @('&amp;') instead of simply @('&').  Thanks to Cuong Chau for pointing
 out that the topic @(tsee double-rewrite) was not being displayed in the
 online manual (back when @('&') was used in the URL in the documentation
 string).</p>

 <p>The "clean" target of "make" has been deprecated since ACL2 Version
 7.4 (released in March, 2017). Its replacement is target "clean-lite"; or,
 use target "clean-all" (or equivalently, "distclean") if you want a more
 thorough cleaning.</p>

 <p>(SBCL only) ACL2 has been updated so that it builds on recent SBCL
 versions.  In particular, the build was broken for SBCL 1.4.7, as SBCL changed
 the ``RDTSC'' timing capability used in @(see memoization).  Thanks to Keshav
 Kini for help with this issue, which has been resolved in ACL2 source file
 @('memoize-raw.lisp'), as explained in the comment there about
 ``read-cycle-counter''.</p>

 <p>(CCL only) Raw Lisp error messages now mention the caller.  Thanks to Eric
 Smith for pointing out that this information wasn't being provided in the ACL2
 loop even though it was being provided in raw Lisp.</p>

 <h3>EMACS Support</h3>

 <p>Removed setting of the buffer coding system from @('emacs/emacs-acl2.el').
 Thanks to Keshav Kini for suggesting this change.  This should avoid certain
 modifications of ``unusual'' characters when saving a file.</p>

 <h3>Experimental Versions</h3>

 <p>The utility @(tsee with-local-state) no longer causes an error in ACL2(p)
 with @(see parallel-execution) enabled.  Thus, neither do @(tsee
 fmt-to-string) and related utilities, which call @('with-local-state').</p>

 ")
other
(defxdoc note-8-2
  :parents (release-notes)
  :short "ACL2 Version  8.2 (May, 2019) 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 8.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>Note that only ACL2 system changes are listed below.  See also @(see
 note-8-2-books) for a summary of changes made to the ACL2 Community Books
 since ACL2 8.1, including the build system.  Also note that with each release,
 it is typical that the value of constant @(tsee *acl2-exports*) has been
 extended, and that 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 built-in function @(tsee fix-true-list) is now a macro that expands to
 a new built-in function, @(tsee true-list-fix), whose definition follows the
 efficient definition of @(see list-fix) that was in @(see community-book)
 @('books/std/lists/list-fix.lisp').  In that book, @(see list-fix) is now a
 macro that expands to @('true-list-fix').  The use of macro-aliases (see @(see
 add-macro-alias)) should generally make this change backward compatible for
 users of @(tsee list-fix).  Thanks to Mihir Mehta for taking the lead on
 implementing these changes and to Jared Davis for permission to integrate
 definitions and documentation from his Kookamara books into the ACL2
 sources.</p>

 <p>Made some improvements pertaining to @(tsee apply$):</p>

 <ul>

 <li>A quoted lambda object that may ultimately be passed as the ``function''
 for a call of @(tsee apply$) may now have a @(tsee declare) form.  See also
 the discussion of @('lambda$') below.</li>

 <li>The macro @(tsee warrant) no longer causes an error for the 800+ ACL2
 primitives that are built into the definition of @(tsee apply$).  Instead, it
 simply avoids generating (needless) conjuncts for those primitives.</li>

 <li>The rewriter can now evaluate ground terms that involve calls of @(tsee
 apply$) or @(tsee badge) on user-defined function symbols.  Note that
 correctness of such an evaluation depends on the truth of corresponding
 warrants, which will be @(see force)d if not known.</li>

 <li>The event formerly named @('def-warrant') is now @(tsee defwarrant).  This
 event may now be @(see redundant); hence @(tsee defun$) may also be
 redundant.</li>

 <li>The @(':')@(tsee args) command now prints the @(see badge) and @(see
 warrant) for a function, and it avoids printing a package prefix in the case
 of @(see unknown-constraints).</li>

 <li>The optimization for caching ``tame compliant'' lambdas, introduced in the
 preceding release (see @(see note-8-1)), has been improved.</li>

 </ul>

 <p>It is no longer illegal to supply an abstract stobj as the so-called
 ``foundational'' (formerly ``concrete'') stobj in a @(tsee defabsstobj) event.
 Thanks to Sol Swords for initiating a discussion leading to this
 enhancement.</p>

 <p>Calls of the function @('synp') were formerly required to result from
 macroexpansion of @(tsee syntaxp) or @(tsee bind-free) calls, or at least
 nearly so.  That restriction has been lifted, although the restrictions on
 calls of @('synp'), @('syntaxp'), and @('bind-free') remain for hypotheses of
 rules of class @(':')@(tsee rewrite), @(':')@(tsee definition), and
 @(':')@(tsee linear), or resulting from evaluation of hypotheses of
 @(':')@(tsee meta) rules.  Thanks to Sol Swords for requesting this change, so
 that @(tsee defevaluator) forms can include @('synp').</p>

 <p>For calls of @(':')@(tsee pso) and related utilities (@(':')@(tsee pso!),
 @(':')@(tsee psof), and @(':')@(tsee psog)), the Time reported in the summary
 is now the original time, not time related to running @(':')@(tsee pso).</p>

 <p>The macro @('delete-assoc') has been renamed @(tsee remove1-assoc), to
 reflect more clearly that at most one pair is removed, and also for
 consistency with Common Lisp nomenclature (where ``delete'' operations are
 generally destructive and ``remove'' operations are not).  Moreover, other
 functions and macros whose name has prefix @('"DELETE-ASSOC"') have been
 similarly renamed to have prefix @('"REMOVE1-ASSOC"'); for example,
 @('delete-assoc-eq') has been renamed @('remove1-assoc-eq').  (The old
 @('"DELETE-ASSOC"')-based names still exist as macros &mdash; indeed, as
 macro-aliases for their renamed versions (see @(see add-macro-alias)) &mdash;
 but those may be deleted in the future.)  Analogous functions and macros have
 been introduced that remove all pairs with a given key, rather than only one;
 see @(see remove-assoc).  (These and related theorems formerly appeared in the
 @(see community-book), @('books/centaur/misc/remove-assoc.lisp').)  Thanks to
 Alessandro Coglio for a query and subsequent discussion leading to these
 changes.</p>

 <p>The @(see system-utilities) @('all-ffn-symbs') and @('all-ffn-symbs-lst')
 are now defined just as macro abbreviations for calls of system utility
 @('all-fnnames1'), thus eliminating some source code duplication.  We may
 deprecate @('all-ffn-symbs') and @('all-ffn-symbs-lst') in the future.</p>

 <p>The implementation of @(tsee verify-termination) has been improved so that
 it no longer can generate (expand to) the form @('(value-triple :redundant)').
 Redundancy is now handled for @('verify-termination') by checking redundancy
 of the generated @(tsee defun) form.  For an example that failed before this
 change, see @(see community-book)
 @('books/system/tests/verify-termination/top.lisp').</p>

 <p>Improvements have been made to the @(see summary) printed on conclusion of
 an event.  It had been possible to have duplicates in the @('"Hint-events"')
 field of the summary; that has been fixed.  Also, the handling of @(':')@(tsee
 instructions) within @(see hints) has changed in the following two ways, to be
 consistent with the use of @(':instructions') at the top level (rather than
 within @(':hints')).  The @('"Rules"') and @('"Hint-events"') fields of
 the summaries incorporate information from calls of the @(see proof-builder).
 Also, the @('"Hint-events"') field no longer contains @('(:CLAUSE-PROCESSOR
 PROOF-BUILDER-CL-PROC)').</p>

 <p>A new variable, @('TRACE-LEVEL'), may be used in calls of @('trace$'); see
 @(see trace$).  This replaces the use of the state global variable of the same
 name, which has been eliminated, thus avoiding an error involving
 @('TRACE-LEVEL') that is mentioned below.</p>

 <p>@(tsee Defun-sk) is now sensitive to the @(see
 default-verify-guards-eagerness), and guard verification is always delayed to
 near the end of the generated event to avoid failures due to the small theory
 present at @('defun') time.  Thanks to Alessandro Coglio for emails on leading
 to these improvements.  Some additional small tweaks have been made to
 @('defun-sk'), in particular to check that there are not two or more distinct
 values associated with @(tsee xargs) keywords @(':verify-guards'),
 @(':non-executable'), or (even if not distinct) @(':guard-hints').</p>

 <p>The function @(tsee integer-range-p) now uses a @(tsee type) @(see
 declaration) in place of the @(':')@(tsee guard), which may slightly improve
 efficiency.  Thanks to Eric Smith for suggesting this possibility.</p>

 <p>The macro, @(tsee thm), may now be used in event contexts, in particular in
 calls of @(tsee encapsulate) and @(tsee progn) and in @(see books).  (See
 @(see embedded-event-form).)  Thanks to Ruben Gamboa for an email that led to
 this change.</p>

 <p>The @(':')@(tsee pf) command now does a more complete job of showing
 induction schemes for induction rules.  (Some corresponding code cleanup has
 also been done.)</p>

 <p>@(see Warnings) about using @(see enable)d rules have been improved.  Now,
 when using an @(see executable-counterpart) rule (which, admittedly, is
 unusual; it is equivalent to using the corresponding @(see definition) rule),
 the warning will correctly recommend disabling the definition rule instead of
 the executable-counterpart rule.</p>

 <p>The logical definition of @('read-file-into-string2') (in support of @(tsee
 read-file-into-string)) has been simplified, and no longer involves @(see
 untouchable) functions symbols.  Thanks to Mihir Mehta for a query that led to
 this enhancement.</p>

 <p>The built-in function @(tsee take) now has a recursive definition, exactly
 along the lines of the old theorem @('take-redefinition') from the community
 book @('books/std/lists/take.lisp') (written by Jared Davis); this theorem has
 now been removed.  The definition of @('take') uses @(tsee mbe), where the
 @(':exec') component calls @('first-n-ac') as before for execution efficiency.
 We thank Mihir Mehta for providing this enhancement, including updates to the
 books.</p>

 <h3>New Features</h3>

 <p>A new macro, @(tsee loop$), is an ACL2 version of the Common Lisp @('loop')
 macro.</p>

 <p>A new construct, @('lambda$'), may be used in place of @('lambda') to be
 passed as the ``function'' for a call of @(tsee apply$).  The syntactic
 requirements for such uses of @('lambda$') are much less strict than for
 quoted @('lambda') objects; in particular, the body need not be in translated
 form (see @(see term)).</p>

 <p>A new macro, @(tsee partial-encapsulate), allows one to introduce
 constrained functions without specifying all of the @(see constraint)s.  This
 functionality was already available using a trust tag, by way of a rather
 convoluted application of @(tsee define-trusted-clause-processor); however,
 @(tsee partial-encapsulate) may be used without a trust tag.  See @(see
 partial-encapsulate), which in particular points to an example of typical
 usage, in @('books/demos/partial-encapsulate.lisp').  Thanks to Sol Swords for
 requesting such a capability.</p>

 <p>There is now, by default, a limit of 9 on the nesting depth of inductions;
 see @(see induction-depth-limit) and to modify this default, see @(see
 set-induction-depth-limit).</p>

 <p>A new @(see evisc-tuple), the @(tsee brr-evisc-tuple), controls printing
 inside the break-rewrite loop.  See @(see brr-evisc-tuple) and @(see
 set-evisc-tuple).</p>

 <p>Many of the @(see brr-commands) now abbreviate (``eviscerate'') by default
 using the new @(tsee brr-evisc-tuple) (see above), and for each for those a
 corresponding command with suffix ``+'' print in full.  For example, such
 commands include @(':path') and @(':path+'); see @(see brr-commands) for the
 full list of commands.  Thanks to Stephen Westfold and others at the 2018
 Developer's Workshop for discussing this issue.</p>

 <p>A new signature is legal for @(tsee clause-processor)s, to support the
 return of rules and event names to be printed in the summary.  See @(see
 make-summary-data).</p>

 <p>@(tsee Apply$) now handles functions that return multiple values.  This has
 widespread ramifications.  The structure of badges has changed.  There is no
 longer an ``authorization-flag'' and there is now an ``out-arity'' slot in the
 badge.  See @(see badge).  Every badged non-primitive function symbol now has
 a warrant.  If @('fn') is a warranted function symbol and returns more than
 one result then @('(apply$ 'fn ...)') returns a list of the results, just as
 @('fn') does in the logic.  See @(tsee apply$).  The warrant of a multi-valued
 function is just like that for a single-valued function except that @(tsee
 mv-list) is used to coerce the output of the multi-valued function to a list.
 See @(tsee warrant).  All @('LAMBDA') objects and @(tsee lambda$) expressions
 must be single-valued, but can use multi-valued functions to compute that
 value.</p>

 <h3>Heuristic and Efficiency Improvements</h3>

 <p>@(tsee Make-event) expansions have often been reduced in size.  (Technical
 note: @('record-expansion') has been inserted only on expansions done directly
 under @(tsee encapsulate) events, and some changes have also been made in how
 and when @(see local) events are elided from expansions.)  The reduction in
 total sizes of @('.cert') files for a complete (``everything'') regression was
 8.8%, though in some cases the reduction was substantially larger: for
 example, the size of @('books/centaur/fty/tests/deftranssum.cert') was reduced
 from 22,474,113 bytes to 16,910,530 bytes, a reduction of nearly 25%.</p>

 <p>A tweak to the rewriter can significantly speed up the use of
 hypothesis-free @(see meta) rules on large terms.  Thanks to Mertcan Temel for
 sending an example that motivated this change, whose time was cut from 67
 seconds to 19 seconds.</p>

 <p>Some small optimizations have been made for the generation of
 executable-counterpart (so-called ``*1*'') code (see @(see evaluation)).</p>

 <p>It has long been the case that certain prover routines, including handling
 of output from @(see meta) functions, transformed results into so-called
 ``quote-normal form'', where for example the @(see term) @('(cons '3 '4)') is
 replaced by @('(quote (3 . 4))').  Now, that transformation avoids recurring
 inside calls of @(tsee hide).  We thank Mertcan Temel, who had a class of
 examples that motivated this change.  One such example took 856.27 seconds of
 `prove' time before this change, but only 270.14 seconds after this change,
 thus eliminating 68.5% of the time.</p>

 <p>Proofs involving very large terms could be slowed down by checking those
 terms for calls of @(tsee if), in support of reporting @(see splitter)s of
 type if-intro.  That check is now limited by avoiding subterms that are calls
 of @(tsee hide).  Thanks to Mertcan Temel for supplying examples, one of which
 exhibited a proof time of 302.06 seconds that was reduced to 123.57 seconds
 with this change, and thanks to Sol Swords and Alessandro Coglio for helpful
 comments on possible enhancements.</p>

 <h3>Bug Fixes</h3>

 <p>Fixed a bug, probably a soundness bug (though we haven't tried to prove
 @('nil') by exploiting it).  The bug is in the computation of the
 ``immediate-canonical-ancestors'' of a function symbol, which is used in the
 implementations of @(see memoization) and @(tsee defattach), as well as in
 interactions between attachments and both @(tsee defaxiom) events and
 @(':')@(tsee meta) rules.  Thanks to Sol Swords for pointing out this bug and
 presenting a helpful example.</p>

 <p>Fixed three @(see proof-builder) bugs:</p>

 <ul>

 <li>Fixed the proof-builder command, @('dv') (see @(see acl2-pc::dv)),
 for diving into calls of @(tsee list) and @(tsee list*).</li>

 <li>Fixed a bug in the proof-builder command, @('geneqv').  Thanks to Shilpi
 Goel for reporting this bug with an example.</li>

 <li>The proof-builder numeric ``diving'' commands @('1'), @('2'), @('3'),
 etc. &mdash; and more generally, the @('dv') command &mdash; were broken when
 the current subterm is of the form @('(if 't .. ..)').  This has been fixed.
 Thanks to Keonho Lee for reporting this bug.</li>

 </ul>

 <p>Eliminated a hard error labeled as ``Implementation error'' that could
 occur when submitting a @(':')@(tsee congruence) rule during the second pass
 of @(tsee encapsulate) or the local incompatibility check in Step 3 of @(tsee
 certify-book).  The error occurred when the equivalence relation of the rule
 had been defined locally, hence was missing during that second pass or local
 incompatibility check.  Now, a useful ordinary (``soft'') error occurs, with a
 useful message.  Thanks to Nathan Guermond for reporting this bug with a
 helpful example.</p>

 <p>It had been possible to enter an infinite loop after certain errors
 involving @(see wormhole)s and state global variables; now, a clean error
 occurs instead.  The specific error motivating this change involved the
 combination of both tracing certain system functions (for example,
 @('pop-accp-fn')) and calling @(tsee accumulated-persistence).  That specific
 error has been eliminated by the change to @(tsee trace$) involving variable
 @('TRACE-LEVEL') that is mentioned in an item above.</p>

 <p>Fixed a bogus error produced by @('defchoose') forms containing unused
 variables with @('ignorable') declarations.  Also eliminated an extra warning
 in the case of more than one bound variable with at least one of them unused,
 which could occur after @('(set-ignore-ok :warn)') has been evaluated.  Thanks
 to Sol Swords for finding these bugs and for supplying code that we installed
 to fix them.</p>

 <p>Fixed an inefficiency in book certification due to calling @(tsee
 fast-alist-free-on-exit) on the wrong objects.  Thanks to Sol Swords for
 pointing out this problem.</p>

 <p>The @('make TAGS') command could fail to do a proper check that the
 @('etags') program is installed, resulting in a failure when attempting to
 build an ACL2 executable.  This has been fixed.  Thanks to Johannes
 Altmanninger for reporting this problem in GitHub Issue #955.</p>

 <p>When a function that calls @(tsee apply$) (or @(tsee apply$-userfn), @(tsee
 badge), or @(tsee badge-userfn)) has been @(see memoize)d with a non-@('nil')
 value for argument @(':aokp'), its memo table may need to be flushed when
 removing a @(see badge).  (Such removal typically occurs by undoing a call of
 @(tsee defun$) or @(tsee defwarrant), perhaps because they are @(see local) to
 an @(tsee encapsulate) event or to a book.)  However, such flushing was not
 being done.  That has been fixed.  See new @(see community-book)
 @('books/system/tests/apply-with-memoization.lisp') for examples.  Among the
 changes made to the source files that are related to this fix: the ``Essay on
 Memoization with Attachments'' has been enhanced to discuss the implementation
 of such flushing; and functions @('doppelganger-apply$-userfn') and
 @('doppelganger-badge$-userfn') (formerly called @('concrete-apply$-userfn')
 and @('concrete-badge$-userfn')), which are still not advertised, are now
 introduced with @(tsee partial-encapsulate) (hence have unknown constraints)
 and are now @(see untouchable).</p>

 <h3>Changes at the System Level</h3>

 <p>The @(see documentation) topic, @(see system-utilities), is now about only
 utilities that pertain to the ACL2 system implementation, rather than
 arbitrary built-in utilities.  Thus, each of the following now has its own
 topic, rather than being described in @(see system-utilities).  (Thanks to
 Alessandro Coglio for suggesting this reorganization.)</p>

 <ul>
 <li>@(tsee alist-keys-subsetp)</li>
 <li>@(tsee alist-to-doublets)</li>
 <li>@(tsee cons-count-bounded)</li>
 <li>@(tsee evens)</li>
 <li>@(tsee keyword-listp)</li>
 <li>@(tsee merge-sort-lexorder)</li>
 <li>@(tsee odds)</li>
 <li>@(tsee packn)</li>
 <li>@(tsee packn-pos)</li>
 <li>@(tsee pairlis-x2)</li>
 <li>@(tsee pairlis-x1)</li>
 </ul>

 <p>Documentation pertaining to @(tsee apply$) and related topics has been
 extended significantly.</p>

 <p>(GCL only) Eliminated compiler output (by setting GCL raw Lisp variables
 @('*compile-verbose*') and @('*load-verbose*') to @('nil')).</p>

 <p>A new documentation topic, @(see efficiency), suggests some ways to speed
 up proofs and evaluation.  The ACL2 community is encouraged to extend (and
 more generally, improve) this topic!</p>

 <p>(LispWorks only) Bytes allocated are now reported in LispWorks (formerly,
 only in CCL and SBCL) by @(tsee time$) and @(tsee memsum).</p>

 <p>A new documentation topic, @(see make-event-example-3), explains the new
 implementation of @(tsee thm), thus providing insight into several common
 implementation techniques used with @(tsee make-event).</p>

 <p>A new documentation topic, @(see rule-classes-introduction), provides a
 basic guide to which sorts of rules to create from your theorems.  Thanks to
 Mihir Mehta for encouraging the development of this topic.</p>

 <p>Fixed ``@('make STATS')'' (which is invoked by ``@('make DOC')'') to
 generate a result file @('doc/acl2-code-size.txt') that gives accurate
 statistics on code size on Linux.  (The relevant @('grep') commands in file
 @('doc/create-acl2-code-size') needed the @('-a') option on Linux.)</p>

 <p>Updated the CCL installation instructions formerly at :DOC ccl-updates.
 The topic is now @(see ccl-installation).  This now replaces the installation
 instructions file @('installation/ccl.html'); thus, the ACL2 community is now
 welcome to improve these instructions.  Thanks to Eric Smith for discussion
 that led to this change and to Keshav Kini and Alessandro Coglio for helpful
 feedback.</p>

 <p>The makefile target @('certify-books') has been deprecated in both
 @('GNUmakefile') and @('books/GNUmakefile').  Thanks to the acl2-books email
 list (in particular we got feedback from Alessandro Coglio, Shilpi Goel, David
 Rager, Eric Smith, and Sol Swords, all helpful) for working through this
 issue.</p>

 <p>A message is now printed when loading file @('~/acl2-init.lsp') at
 startup.</p>

 <h3>EMACS Support</h3>

 <p>Fixed the @(see acl2-doc) browser so that it can handle topic names with
 the single-quote (@(''')) and comma (@(',')) characters, by escaping them.</p>

 <p>Fixed Emacs support for the @(see proof-builder) dive command (see
 @(see acl2-pc::dive)), @('control-t control-d'), to eliminate trailing zeros,
 since those are (and have been) disallowed by that command.</p>

 <p>A new @(tsee acl2-doc) command is the question-mark character (@('?')),
 which goes to a page with one-line command summaries.  Thanks to Warren Hunt
 for a request leading to this enhancement.</p>

 <h3>Experimental Versions</h3>

 ")
other
(defxdoc note-8-3
  :parents (release-notes)
  :short "ACL2 Version  8.3 (April, 2020) 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 8.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.  See also @(see
 note-8-3-books) for a summary of changes made to the ACL2 Community Books
 since ACL2 8.2, including the build system.  Also note that with each release,
 it is typical that the value of constant @(tsee *acl2-exports*) has been
 extended, and that 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>It is now permitted for an evaluator to be ancestral in a metafunction or
 clause-processor.  See @(see evaluator-restrictions), or see the source code
 comment ``Essay on Correctness of Meta Reasoning'', for discussion of the
 remaining restrictions.  Thanks to Sol Swords for requesting this improvement
 and for many helpful discussions.  Moreover, he found a bug in a proof in the
 above Essay, which has been fixed; he made a key observation that led to
 completion of that fix.  Also thanks to Rob Sumners for helpful
 discussions.</p>

 <p>The @(see accumulated-persistence) utility no longer overcounts accumulated
 frames due to nested (recursive) rule applications.  Although that shortcoming
 was documented, it was unfortunate and we thank Sol Swords for an email that
 nudged us into making this improvement and provided helpful insight, and Eric
 Smith for suggesting this improvement more than 10 years ago (!).</p>

 <p>In a (new-style) signature, any symbol whose @(tsee symbol-name) is
 @('"*"') now designates a non-@(see stobj) argument.  Formerly, only the
 symbol @('*') in the @('"ACL2"') package could be used in that way.  Thanks
 to Jared Davis for suggesting (in 2007!) that we consider such a change.</p>

 <p>More functions can now be given @(see warrant)s.  In particular: the
 requirement of a natural number measure for recursive definitions has been
 relaxed to allow lexicographic combinations of natural numbers as defined by
 the @('llist') function in the Community Books at @('books/ordinals/'), and it
 is possible to warrant some functions that use local @(see stobj)s as long as
 they don't call @(tsee apply$).  See @(see defwarrant).</p>

 <p>The function @(tsee symbol-name-lst) is now a @(see guard)-verified @(see
 logic)-mode function (formerly it was a @(see program)-mode function).  Thanks
 to Alessandro Coglio for suggesting that it might be good to document this
 function, which led us to this change (and to its being documented).</p>

 <p>The pattern language for the macro, @(tsee case-match), now includes the
 case @('(quote~ sym)'), where @('sym') is a symbol and this case matches any
 symbol whose @(tsee symbol-name) is @('(symbol-name sym)').</p>

 <p>The following symbols, when used in special syntactic roles in the macro
 @(tsee loop$), may be in any package: @('for'), @('in'), @('on'), @('from'),
 @('to'), @('by'), @('of-type'), @('when'), @('until'), @('sum'), @('collect'),
 @('always'), @('thereis'), and @('append').  Thanks to Mertcan Temel for
 requesting this enhancement.</p>

 <p>@(':Expand') @(see hints) now act more reliably for @(see
 equality-variants), by expanding away @(see guard-holders).  Thanks to Sol
 Swords for supplying this enhancement and sending the following example that
 works now but formerly failed:</p>

 @({
 (defthm member-of-cons
   (equal (member x (cons x y)) (cons x y))
   :hints(("Goal" :in-theory (disable member)
           :expand ((member x (cons x y))))))
 })

 <p>An analogous improvement has been made for @(':by'), @(':use'), and
 @(':hands-off') hints.</p>

 <p>The macros @(tsee defequiv), @(tsee defrefinement), and @(tsee defcong) now
 conform to the following principle discussed in a new @(see documentation)
 topic, @(see packages-for-generated-symbols): ideally, utilities generate
 symbols in the @(tsee current-package), at least by default.  These three
 macros now have a @(':package') keyword argument whose default value is
 @(':current'); with this value the macros conform to the above principle.  See
 their @(see documentation) topics.  To get the previous behavior, use the
 @(':legacy') value.  (Another way to deal with failures caused by this change
 may be to fix packages when referring to generated symbols, such as changing
 @('acl2::x-equiv') to @('x-equiv').)  In particular, the @(':legacy') option
 was used to update definitions in the @(see community-books) for macros that
 generate @(tsee defcong) forms.  Also, all three macros now do some
 error-checking (rather than leaving that entirely to the generated @(tsee
 defthm) form), and the unsupported @(':doc') keyword argument has been removed
 from these macros.  Thanks to Pete Manolios for suggesting all of these
 changes, and for providing not only implementations but also modifications to
 the @(see community-books).</p>

 <p>The translation of a term @('(and t u0)') is @('(if 't u1 'nil)'), where
 @('u1') is the translation of @('u0').  That term, @('(if 't u1 'nil)'), is
 now generally displayed to the user (``@(see untranslate)d'') as @('(and t
 u0)'), but formerly it was displayed as @('u0'), which could be confusing.
 Thanks to Stephen Westfold, who sent an example showing how, when using the
 @(see proof-builder)'s @('REWRITE') command to replace a subterm @('a0') by
 @('t') in a term @('(and a b)') could lead to confusion, since the resulting
 @('(and t b)') was printed only as @('b').  Note:  For Boolean contexts, the
 analogous change was also made for terms @('(and u0 t)').</p>

 <p>It no longer causes an error to call @(tsee trans-eval) on an expression
 that references a locally-bound @(tsee stobj), that is, one bound by @(tsee
 with-local-stobj) or @(tsee stobj-let).  The user is responsible for
 understanding that when calling @('trans-eval'), all stobj variables in the
 supplied expression refer to globally-bound stobjs, that is, stobjs stored in
 the @('user-stobj-alist') field of the ACL2 @(tsee state).  See the new
 documentation topic, @(see trans-eval-and-locally-bound-stobjs), for relevant
 discussion.  (Another topic, @(see user-stobjs-modified-warnings), may also be
 helpful for understanding the interaction of @('trans-eval') with stobjs.)
 Thanks to Sol Swords for suggesting this change and convincing us of its
 suitability.</p>

 <p>The @(tsee defstobj) event now supports @(see stobj)s with fields that are
 hash tables in raw Lisp but are represented logically as association lists.
 Thanks to Sol Swords for providing not only the design but also the
 implementation, which was moved from community book
 @('books/add-ons/hash-stobjs.lisp') into the ACL2 sources (with small
 modifications to both the new code and existing code).  That book still
 provides lemmas that may be helpful for reasoning about hash-table fields, as
 well as some tests.  See also @(tsee defstobj).</p>

 <p>Added suitable @(see guard)s, with custom error messages, to @(tsee
 add-invisible-fns) and to @(tsee remove-invisible-fns).  Also removed
 confusing messages for each in the case of redundancy.  Thanks to Pete
 Manolios for pointing us to a bug in the documentation for the latter (which
 we have fixed), which led us to the addition of guards.</p>

 <p>The notion of <i>untouchable</i> macro is no longer directly supported.
 Specifically: the form @('(push-untouchable SYM t)') is now illegal if
 @('SYM') is already the name of a macro; and after this call of @(tsee
 push-untouchable) it is illegal to define @('SYM') as a macro.  However, a
 macro can be made effectively untouchable by defining it with the new utility,
 @(tsee defmacro-untouchable).  Note that the alleged support for untouchable
 macros was already incomplete, as explained in an example in the form
 @('(defxdoc note-8-3 ...)') in @(see community-book)
 @('books/system/doc/acl2-doc.lisp').</p>

 <p>The @(see event) macro, @(tsee thm), is now treated like @(tsee defthm) in
 the following way: if keyword @(':hints') is supplied, then the hints are
 checked syntactically when skipping proofs (see @(see ld-skip-proofsp)) except
 during @(tsee include-book) or the second pass of @(tsee encapsulate).  For
 example, evaluation of the form @('(thm (equal x x) :hints bad-hints)') now
 causes an error after evaluating @('(set-ld-skip-proofsp t state)'), while
 before this change, it did not.</p>

 <p>The default slow-alist-action (see @(see slow-alist-warning)) is now
 @(':break') instead of @(':warning') in ACL2.  (It remains @(':warning') in
 ACL2(p); see @(see unsupported-waterfall-parallelism-features).)</p>

 <p>For a user-defined @(':')@(tsee induction) rule to be applied, it is no
 longer required for the induction scheme associated with a recursive
 definition to be enabled.  For an example of the effect of this change, see
 the @(see community-book),
 @('books/system/tests/induction-rule-with-disabled-scheme.lisp').  Thanks to
 Pete Manolios for reporting this issue, including the sending of the events in
 that book.  Also see @(see induction) (as that documentation has been
 updated).</p>

 <p>An undocumented kind of @(see fake-rune) is no longer reported by @(tsee
 show-accumulated-persistence).  Thanks to Eric Smith for bringing this issue
 to our attention.</p>

 <p>The algorithm for removing @(see guard-holders) has been modified to avoid
 diving into calls of @(tsee hide).  However, it is possible to obtain the
 former behavior; see @(see guard-holders).</p>

 <p>Since its earliest years, ACL2 uses evaluation to simplify ground
 terms (terms with no free variables).  ACL2 would sometimes generate a call of
 @(tsee hide) around a term that fails to evaluate because of an attempt to
 call a constrained function.  Now, that call incorporates a comment saying
 which constrained function is responsible for the failure.  See @(see
 comment).  Also see @(see hide) for how to fix proof failures caused by this
 new behavior by using @(':expand') @(see hints) or even by turning off this
 new behavior using @(tsee defattach).  Thanks to Rob Sumners (in 2003),
 Francisco J. Martin-Mateos (in 2004), and Anna Slobodova (in 2005), perhaps
 among others, for discussions leading to this enhancement.</p>

 <p>Both @(':')@(tsee puff) and @(':')@(tsee puff*) have been made more
 robust.  Related changes include:</p>

 <ul>

 <li>A new table, @('puff-included-books'), generally prevents the same book
 from being puffed more than once.</li>

 <li>Book directories are tracked more carefully, which can prevent
 errors.</li>

 <li>We no longer allow @(':puff*') to puff non-trivial @(tsee encapsulate)
 events.  (For a technical discussion of reasons for this change, see comments
 in function @('puffed-command-sequence') in ACL2 source file
 @('ld.lisp').)</li>

 <li>Changes to the @(tsee acl2-defaults-table) no longer persist outside the
 scope of a puffed @('encapsulate') event.</li>

 <li>A @(tsee theory-invariant) event no longer
 stores the event @('(in-theory (current-theory :here))') in
 the @(see world).</li>

 </ul>

 <h3>New Features</h3>

 <p>A new @(tsee xargs) keyword, @(':guard-simplify') (default @('t')),
 controls certain simplifications that may be applied to the guard conjecture
 while generating the initial goal.  Setting it to @('nil') skips all
 simplifications that depend on the set of currently @(see enable)d rules.  See
 @(see verify-guards).  Thanks to Sol Swords for designing this feature and
 providing its implementation, along with documentation and corresponding
 adjustments to the community books.</p>

 <p>Now @(tsee defstub) accepts the same keywords as @(tsee encapsulate), both
 for the new-style signatures and for the old-style signatures.  Thanks to
 Alessandro Coglio for suggesting and implementing this enhancement.</p>

 <p>New function @('(maybe-flush-and-compress1 name ar)') calls
 @('(flush-compress name)') and then returns @('(compress1 name ar)'), except
 that all this is skipped if the given array is already compressed.</p>

 <p>A new utility, @(tsee swap-stobjs), does what its name suggests: it swaps
 @(see stobj)s.  Thus, if @('st1') and @('st2') are stobjs then after returning
 from execution of a call @('(swap-stobjs st1 st2)') of @('swap-stobjs'), the
 global value of stobj @('st1') will be the old value of @('st2') and the
 global value of stobj @('st2') will be the old value of @('st1').  See @(see
 swap-stobjs).  Thanks to Sol Swords for requesting this feature and for
 helpful discussions about it.</p>

 <p>By invoking @('(set-absstobj-debug :ignore)'), which requires an active
 trust tag (see @(see defttag)), one can defeat invariance checks for abstract
 stobj fields that otherwise are protected by specifying @(':protect t') (or by
 using the @(':protect-default') keyword to get that effect).  See @(see
 defabsstobj).  Thanks to Sol Swords for suggesting consideration of adding
 some such capability.  In a few preliminary tests we found an average drop of
 about 3.5% in the time it took to run the tests.</p>

 <p>It is now permitted to define functions in which recursive calls occur from
 inside @(tsee loop$) statements.  See @(tsee loop$-recursion).  Such functions
 do not automatically suggest induction schemes.  Furthermore, care must be
 taken when formulating inductively provable theorems about such functions.
 See @(see loop$-recursion-induction) and @(tsee definductor).</p>

 <p>You can now change the second line in the startup banner for a GitHub
 version of ACL2 obtained between releases.  See @(see startup-banner).  Thanks
 to Andrew Walter for requesting this enhancement.</p>

 <h3>Heuristic and Efficiency Improvements</h3>

 <p>ACL2 keeps a complete list of all the runes in the tau database (see @(see
 introduction-to-the-tau-system)).  Formerly this list was duplicate-free, but
 that is no longer the case.  As a result we have seen some faster performance;
 in particular, this change has cut 17% from the time to include the community
 book, @('"centaur/sv/top"').</p>

 <p>Made slight efficiency improvement for @(see table) update (@(':put'))
 events.</p>

 <p>Improved efficiency of the maintenance of @(see stobj)-related arrays (the
 so-called stobj accessor arrays) by using the new function, @(tsee
 maybe-flush-and-compress1).  That code is related to printing stobj field
 accesses using field names rather than indices.  (For background on printing
 untranslated terms, see @(see term).)  For example, after evaluating
 the form @('(defstobj st fld)'), the form</p>

 @({
 (thm (equal (fld st) xxx)
      :hints (("Goal" :in-theory (disable nth))))
 })

 <p>produces the (untranslated) goal @('(EQUAL (NTH *FLD* ST) XXX)') rather
 than @('(EQUAL (NTH 0 ST) XXX)').  A further change has been to reduce the
 frequency of ensuring that those @(see arrays) are up-to-date.  (Technical
 note: this latter change is to source function @('update-wrld-structures'),
 which has an explanatory comment, including an example of a 2.6% time
 reduction.)</p>

 <p>Improved the speed of @(see theory) updates by avoiding repeated length
 computations.  As a result, we have seen about a 5% time reduction on MacOS,
 and between 3% and 4% on Linux, for executing the form, @('(include-book
 "centaur/sv/top" :dir :system)').</p>

 <p>The definition of the macro @(tsee ec-call) has been tweaked to speed up
 compilation in some cases when the host Lisp is SBCL.  In particular, for
 admitting the definition of @('apply$-prim') in @(see community-book)
 @('books/projects/apply-model-2/apply-prim.lisp') with host Lisp SBCL, we have
 seen the time decrease from 1294.33 seconds to 8 seconds.</p>

 <p>A heuristic for ``lazy'' rewriting of calls of @('mv-nth') has been made
 much more efficient in some cases.  Thanks to Sol Swords for investigating
 performance issues leading him to implement such a change, and for making
 modifications to @(see community-books) so that they continue to certify after
 the change.  Those interested in implementation details may start with source
 function @('simplifiable-mv-nth1').</p>

 <p>The raw Lisp representation of @(see stobj)s has been improved to avoid
 some indirection in two ways: a scalar field (one that is not an array or hash
 table) with non-trivial type had been wrapped in a one-element array, but no
 longer; and if there is only one field, and it is an array or hash table, then
 that field is the entire stobj.  (The first change is however avoided when the
 host Lisp is GCL.)  Thanks to Warren Hunt and Sol Swords for suggesting these
 changes.  Technical note: in the course of making these changes, a bug was
 exposed in source function @('raw-ev-fncall'); that has been fixed.</p>

 <p>Reduced the computation and consing for @(see theory) management, which
 might reduce time by a percent or two when including some books.  (Technical
 note.  The idea was to expand the cases in which the use of @(tsee compress1)
 is replaced by more efficient code.  That code is specific to enabled
 structures and may be found in ACL2 source function
 @('update-enabled-structure-array').  We also arranged, in
 @('load-theory-into-enabled-structure'), to double the array size when that
 exceeds the expansion by a minimal suitable multiple of 500.)</p>

 <p>Changed how @(see compound-recognizer) rules are stored in the logical
 @(see world) (per function symbol, rather than in a single alist), which a few
 experiments suggest might reduce time by a couple percent or so.</p>

 <p>A tweak was made to how properties are ordered when stored in the ACL2
 logical @(see world), which experiments show provides small speed-ups.
 (Technical note: the change is to constant
 @('*current-acl2-world-key-ordering*'), and also, functions @(tsee
 symbol-class) and @(tsee logicp) avoid calling @(tsee getprop) for the symbol,
 @('cons').)</p>

 <p>ACL2 now avoids @(see summary) calculations during @(tsee include-book).
 We have seen this change cut more than 9% of the time for the event
 @('(include-book "centaur/sv/top" :dir :system)').</p>

 <p>We now avoid translation of @(tsee default-hints) for termination proofs
 during @(tsee include-book).  We have seen this change cut more than 4% of the
 time for the event @('(include-book "centaur/sv/top" :dir :system)').</p>

 <p>ACL2 now saves, in @(see certificate) files, the translated bodies of
 @(tsee defun) and @(tsee defthm) @(see events).  (See @(see term) for a
 discussion of translated terms.)  This can speed up @(tsee include-book); for
 example, we have measured approximately a 3% reduction in time for the event,
 @('(include-book "centaur/sv/top" :dir :system)'), but with a space
 trade-off of about 41% more bytes allocated.  (Implementation note: the
 relevant algorithms and code are discussed in an expanded version of the Essay
 on Cert-data in the ACL2 source code.)  Thanks to Eric Smith for pointing out
 a bug (which we then fixed) in a preliminary implementation of this
 feature.</p>

 <p>Some stack overflows may be avoided by a change to a built-in system
 function, @('cons-count-bounded-ac'), so that it is now tail recursive as it
 CDRs the list, rather than as it takes the CAR.  Thanks to Shilpi Goel for
 reporting the problem with an example and to Sol Swords for suggesting this
 fix.  That example exhibited a second stack overflow, due to a built-in
 memoized system function that is no longer called when computing a call of the
 built-in system function, @('pkg-names').</p>

 <p>The second pass of @(tsee encapsulate) now uses @(see fast-alists) when
 calculating new triples in the logical @(see world) (in ACL2 system function
 @('new-trips')).  We have seen this change result in cutting the time by 4.7%
 and the bytes allocated by 34% for including the community book,
 @('"centaur/sv/top"').</p>

 <p>Computation of the @(see guard) proof obligation has been sped up in some
 cases involving evaluation of ground terms (terms without free variables).
 Thanks to Warren Hunt for sending us an example that prompted us to make this
 change.</p>

 <h3>Bug Fixes</h3>

 <p>As noted in the documentation for @(see lemma-instance), ACL2 may avoid
 proving some constraints required for @(see functional-instantiation) that
 were previously proved.  There was such support even in the case that the
 previous proof was done on behalf of a @(tsee defattach) event, but that
 support has been made more complete (by keeping more functional substitutions
 in canonical form).</p>

 <p>A hard Lisp error has been fixed that could occur (probably only rarely)
 after adding rules of class @(':')@(tsee definition) that introduce
 recursion.</p>

 <p>The function @(tsee meta-extract-formula) could return a non-trivial
 value (i.e., not @(''T')) when applied to a @(see program)-mode function.  We
 thank Sol Swords for reporting this bug with a proof of @('nil') that
 exploited it.  This soundness bug has been fixed.  That work led us to fix the
 following related bugs (which could also be soundness bugs, though we have not
 checked).  First, the function @(tsee fncall-term) could similarly return a
 non-trivial value when applied to a program-mode function.  Second, the
 utility @(tsee mfc-rw), as well as other such @('mfc-xx') utilities in support
 of @(see extended-metafunctions) and @(tsee meta-extract-contextual-fact),
 could be called on terms containing program-mode function symbols.</p>

 <p>Eliminated an error occurring when attempting to compute the guard proof
 obligation for a constrained function, in particular, when using the
 @(':')@(tsee gthm) utility on such a function (also see @(see guard-theorem)).
 Thanks to Alessandro Coglio for pointing out this bug and for noting that
 @('t') could be a reasonable result for the guard theorem in such cases.</p>

 <p>Fixed ACL2 raw Lisp error caused by @(see add-default-hints!).  Thanks to
 Pete Manolios for debugging this problem.</p>

 <p>Fixed a bug in the @(see proof-builder) command @('apply-linear') (and its
 abbreviation, @('al')), which was making it impossible to save an event after
 an interactive session that includes such a command.  Thanks to Mihir Mehta
 for bringing this bug to our attention and sending an example.</p>

 <p>Fixed a bug in @(tsee defun-sk), which was generating a @(tsee
 verify-guards) or @('verify-guards?') event with @(':guard-hints') instead of
 @(':hints').  Thanks to Alessandro Coglio for reporting this bug and providing
 the fix.</p>

 <p>The use of @(':stack :pop') in the macro @(tsee with-output) failed to
 restore @(see gag-mode) properly.  For example, the use of
 @('(with-output :stack :push :gag-mode nil (with-output :stack :pop <form>))')
 failed to run @('<form>') with the existing value for gag-mode (default:
 @(':goals')).  Thanks to Mihir Mehta for a query that led us to make this
 fix.  Technical note: state global @('inhibit-output-lst-stack') is now a list
 of pairs @('(inhibit-output-lst . gag-mode)'); see @(see with-output).</p>

 <p>The @(see proof-builder)'s @('DV') command was broken for expressions of
 the form @('(if t term1 term2)'); for example, @('(verify (if t x y))')
 followed by @('1'), @('2'), or @('3') caused a raw Lisp error.  Thanks to
 Stephen Westfold for bringing this bug to our attention and pointing out the
 fix.</p>

 <p>We fixed a bug in the implementation of @(tsee encapsulate) that could
 cause a hard ACL2 error (``Unexpected expansion-alist ... for second pass of
 encapsulate'').  Thanks to Pete Manolios for sending an example that exhibited
 this bug.  (A slightly simplified version of his example may be found in
 a comment in the definition of function @('encapsulate-pass-2'), ACL2 source
 file @('other-events.lisp').)</p>

 <p>@(tsee Defstobj) now provides a suitable error message, instead of an
 implementation error, when new names are duplicated after renaming.  Here are
 examples that now have improved error messages.</p>

 @({
 (defstobj st x :renaming ((create-st x)))
 (defstobj st fld :renaming ((fld create-st)))
 (defstobj st fld1 fld2 :renaming ((fld1 fld) (fld2 fld)))
 })

 <p>We fixed an obscure error message when attempting to @(see memoize) either
 @('IF') or @('RETURN-LAST'), and we improved the @(see memoize) documentation
 to mention these and other restrictions on what can be memoized.</p>

 <p>Fixed erroneous @(see type) declarations in array copying
 functions.  (Technical notes.  (1) It's not clear that these bugs have ever
 had any effect.  (2) Those source code functions have been renamed by dropping
 their @('"stobj-"') prefixes from @('stobj-copy-array-xxx'), now that one of
 them has application to other than stobjs, in new code mentioned above for
 enabled structures.)</p>

 <p>Fixed the process of translating the @(see type-spec), @('standard-char'),
 into a @(see term).  For example, the following definition failed but now
 succeeds:<br/> @('(defun foo (x) (declare (type standard-char x)) (cons 3
 x))').</p>

 <p>Fixed a bug that could cause the wrong @(see stobj) to be displayed by
 @(tsee print-gv), when congruent stobjs with a single bit-array field are
 involved.  See a comment in ACL2 source function
 @('apply-user-stobj-alist-or-kwote') for an example of this bug.</p>

 <p>When including a book that is uncertified because of a stale @(see
 certificate) file, ACL2 was inappropriately using information about @(see
 type-prescription) rules (specifically, those computed by the system at
 definition time) that was stored in that certificate.  This has been fixed,
 thanks to a bug report from Eric Smith about a related feature mentioned
 above, on saving translated bodies in certificate files.  Moreover, the
 relevant system function, @('include-book-fn1'), has been modified to do a
 better job of ignoring certificate files of uncertified books.</p>

 <p>The utility @('set-saved-output') has been badly broken for years, but
 without complaints (other than from one of us shortly before the release),
 suggesting that it hasn't been directly called by users.  So we have
 eliminated it.</p>

 <h3>Changes at the System Level</h3>

 <p>The makefile target @('certify-books') has been removed from
 @('GNUmakefile') and @('books/GNUmakefile').  It was deprecated in the
 preceding release, where we thanked the acl2-books email list (in particular
 we got feedback from Alessandro Coglio, Shilpi Goel, David Rager, Eric Smith,
 and Sol Swords, all helpful) for working through this issue.</p>

 <p>The keyword @(':ACL2') is now a member of the Lisp global, @('*features*'),
 which allows other programs to use read-time conditionals @('#+acl2') /
 @('#-acl2') to indicate the presence or absence of ACL2.  Thanks to Andrew
 Walter for suggesting that this might be useful, for example for Quicklisp
 code.</p>

 <h3>EMACS Support</h3>

 <p>The command `@('Ctl-t p')' now works in Emacs 25.</p>

 <p>The @(see acl2-doc) browser for ACL2+books documentation can be extended
 with a new command, @('U'), to open a URL (or in some cases, a file) in a
 browser.  See file @('emacs/acl2-doc-open-url.el') for more information.</p>

 <h3>Experimental Versions</h3>

 ")
other
(defxdoc note-8-4
  :parents (release-notes)
  :short "ACL2 Version  8.4 (August, 2021) 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 8.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.  See also @(see
 note-8-4-books) for a summary of changes made to the ACL2 Community Books
 since ACL2 8.3, including the build system.  Also note that with each release,
 it is typical that the value of constant @(tsee *acl2-exports*) has been
 extended, and that 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>@(tsee Apply$), @(tsee lambda$), and @(tsee loop$) may be used with @(see
 badge)d @(':')@(tsee program) mode functions in top-level evaluation.  To
 assign a badge to a @('program') mode function, use the new feature @(tsee
 defbadge).</p>

 <p>For calls of the form @('(HIDE (COMMENT "..." ...))'), the string is a
 bit more descriptive.  See @(see comment) and see @(see hide).  Thanks to Mark
 Greenstreet for helpful discussions leading to this change.</p>

 <p>The @(see events) @(tsee defun-nx) and @(tsee defund-nx) now @(see disable)
 the @(see executable-counterpart) @(see rune) for the new function symbol.
 Thus, after either of these introduces function symbol @('f'), the ACL2
 rewriter will no longer attempt to simplify a call of @('f') on concrete
 arguments by using evaluation (unless of course that executable-counterpart is
 enabled first).  Thanks to Mark Greenstreet for an email leading to this
 change.  The implementation of this change also fixes a bug: when the @(see
 default-defun-mode) is program mode, @(tsee defund-nx) now @(see disable)s the
 definition @(see rune) for the new function, but that was not previously the
 case.</p>

 <p>Some built-in functions supporting the macro, @(tsee position), now @(tsee
 fix) (coerce) their accumulator argument to a natural number.  Thanks to Mihir
 Mehta for supplying the initial such changes, for the purpose of avoiding
 numeric type hypotheses.  After that, thanks to email correspondence from
 Warren Hunt, we added built-in @(':')@(tsee type-prescription) rules for those
 same functions so that ACL2 @(see type-set) reasoning infers that
 @('position') always returns either @('nil') or a natural number.</p>

 <p>The macro @(tsee defconst) no longer accepts an optional documentation
 string (which was already being ignored).  Thanks to Eric Smith and Alessandro
 Coglio for suggesting this change, which avoids potential confusion; consider
 for example @('(defconst *c* () "abc")').</p>

 <p>Two improvements have been made in support of the @(tsee case-match) macro.
 (1) The built-in constant @(tsee *acl2-exports*) now includes the
 @('"ACL2"') package symbol, @('quotep~').  (2) The built-in function
 @('symbol-name-equal') is now a @(see guard)-verified @(':')@(tsee logic) mode
 function.  Thanks to Stephen Westfold for email leading to these changes:
 for (1), pointing out that the special role of @('quotep~') for the @(tsee
 case-match) macro applies only to that @('"ACL2"') package symbol, not to
 other symbols with the same name; and for (2), pointing out that the expansion
 of a @('case-match') call that invokes @('quotep~') for matching was
 introducing @(':')@(tsee program) mode code.</p>

 <p>A call of @(tsee comment) is more often inserted when the prover inserts a
 call of @(tsee hide).  See @(see comment) for a discussion of such ways in
 which @('comment') is used.</p>

 <p>When a @(see rewrite) rule's conclusion is of the form @('(equiv term1
 term2)') where @('equiv') is a known @(see equivalence) relation, ACL2
 generally creates the rule to rewrite an instance of @('term1') to the
 corresponding instance of @('term2'), in a context where it is sufficient to
 preserve @('equiv').  However, if that rule is illegal, for example because it
 would rewrite a variable, then the rule is effectively treated as @('(equal
 (equiv term1 term2) t)').  This behavior is not new, but now an explanatory
 @(see observation) is printed when this happens, as for @('foo') in the
 following example.  Thanks to Mihir Mehta for suggesting such an
 enhancement.</p>

 @({
 (defun my-equiv (x y) (equal x y))
 (defequiv my-equiv)
 (in-theory (disable my-equiv)) ; optional (avoids warnings for the next form)
 (defthm foo (my-equiv x (car (cons x x))))
 })

 <p>A trust tag (see @(see defttag)) is now required to set the @(see
 ld-prompt) to a non-Boolean value, other than the @(see brr) prompt, since
 that can cause printing of the prompt to modify state in rather arbitrary
 ways.</p>

 <p>Improved translation of function calls, especially those that involve
 congruent @(see stobj)s, including better error messages, much improved code
 comments, and simplified code.  Thanks to Sol Swords for sending an example
 with a misleading error message.</p>

 <p>The error message has been improved when a @(':')@(tsee linear) rule is
 illegal due to simplification of its conclusion to a constant by ground
 evaluation.  Thanks to Eric Smith for suggesting such an improvement.</p>

 <p>It is no longer an error to repeat a @(tsee defun-sk) event after removing
 or adding the @(see xargs) @(see declaration), @(':guard t'); the latter is
 now essentially redundant.  It is similarly no longer an error to repeat a
 @('defun-sk') event by adding, removing, or changing keyword @(':guard-hints')
 in an @('xargs') declaration.  Thanks to Alessandro Coglio for reporting these
 issues.</p>

 <p>The set of @(tsee apply$) primitives has been expanded.  These are built-in
 function symbols that do not need a @(see warrant) when reasoning about the
 application of @('apply$') to them or using them in @(tsee loop$).  Thanks to
 Alessandro Coglio for noting that some built-in @(':')@(tsee logic)-mode
 functions do not have warrants, in particular, @(tsee sublis-var).</p>

 <p>Improved @(tsee defwarrant) to be a no-op for @(tsee apply$)
 primitives.</p>

 <p>ACL2 now points out when specious simplification takes place; see @(see
 specious-simplification).  Formerly this was the case only with @(see
 gag-mode) turned off; still, @('prove') output needs to be on for any such
 message to be printed (see @(see set-inhibit-output-lst)).  Thanks to Mihir
 Mehta for a query that led to this enhancement.</p>

 <p>For @(tsee fmt) directives @('~f') and @('~F'), ACL2 now uses the alist
 component of the @('evisc-tuple') argument and the global @(tsee evisc-table).
 Previously it used these only for directives @('~x'), @('~y'), @('~X'), and
 @('~Y') (and deprecated directives @('~p') etc.; see @(see fmt)).  Thanks to
 Eric Smith for a query leading to this enhancement.</p>

 <p>Reporting has been improved when encountering possible invariance
 violations for abstract @(see stobj)s.  Now, when that happens an
 ``illegal-state'' is entered, as indicated by the prompt, and instructions are
 printed for how to proceed at your own risk.  See @(see illegal-state).</p>

 <p>A @(tsee table)'s guard may now reference the ACL2 @(see state).  Thus, it
 may now be a term involving (at most) the variables @('WORLD'), @('ENS'), and
 @('STATE').</p>

 <p>It is now always redundant to @(tsee unmemoize) a function symbol that is
 not currently @(see memoize)d.  See @(see redundant-events).</p>

 <p>The ``basic'' ruler-extenders (see @(see rulers)) now include not only the
 symbols @(tsee return-last) and @(tsee mv-list) but also the symbol @(tsee
 if).  As before, the termination analysis always continues through the true
 and false branches of @('IF') calls; but now, by default, it also continues
 through the first argument of an @('IF') call.  Thanks to Eric Smith for
 suggesting this improvement and testing it on some proprietary books.</p>

 <p>When supplying @('state') as an argument to @(tsee defun-nx) (or @(tsee
 defund-nx)), it is no longer necessary to declare @('state') as a @(see stobj)
 or use @(tsee set-state-ok).  Thanks to Eric Smith for suggesting the
 possibility of this change.</p>

 <p>It had been the case that if @(tsee defun-nx) or @(tsee defund-nx) is used
 for a recursive definition, and that form specifies a value for
 @(':ruler-extenders') that omits @(tsee return-last) (see @(see rulers) for
 relevant background), then the definition generally fails to be admitted.
 (This is due to the generated @(tsee defun)'s use of @(tsee prog2$), which is
 a macro that abbreviates a call of @(tsee return-last), which blocks the
 termination analysis.)  That has been fixed, by ensuring that @('defun-nx')
 and @('defund-nx') arrange that @('return-last') is always among the
 ruler-extenders of the generated @(tsee defun) form.  Thanks to Eric Smith for
 noticing this issue and for a helpful discussion.</p>

 <p>Improved handling of @(see linear) rules: cause an error with a helpful
 message when a linear rule is no longer created during @(tsee include-book) or
 the second pass of an @(tsee encapsulate) form, and optimize by avoiding
 certain calculations when the @(':trigger-terms') keyword is supplied.  Thanks
 to Eric Smith for sending an example that illustrates the former issue,
 essentially as included in a comment in @(see community-book)
 @('books/system/doc/acl2-doc.lisp'), form @('(defxdoc note-8-4 ...)').</p>

 <p>The @(see event) macros @(tsee value-triple) and @(tsee assert-event) have
 been changed to be more flexible, in particular by providing an option to
 allow the given form to return multiple values.  They are also more efficient,
 as they no longer evaluate using @(see safe-mode) by default.
 (Technical note: As a consequence of implementation changes, one will rarely
 if ever see ``hard'' errors (see @(see er)) from these utilities.)  Thanks to
 Eric Smith for requesting that a single utility encompass what is provided by
 the built-in utility @(tsee assert-event) and the @(see community-books)
 utilities @(tsee assert!) and @(tsee assert!-stobj).  That single utility is
 now @(tsee assert-event), which in turn uses @('value-triple') to check the
 supplied assertion.</p>

 <p>The ACL2 @(tsee bdd) package can now reason using the implicit rewrite rule
 @('(equal (consp (cons x y)) t)').  Thanks to Warren Hunt for requesting this
 enhancement.</p>

 <p>The @(see event) macro @(tsee with-output) has been improved with several
 changes and new features (and correspondingly, so has @('with-output!')).  In
 addition to improvements to its documentation, these include the following;
 see @(tsee with-output) for more information.</p>

 <ul>

 <li>The keyword argument @(':summary') has been replaced by keyword arguments
 @(':summary-on') and @(':summary-off'), which control inhibited summary types
 in analogy to how keyword arguments @(':on') and @(':off') control inhibited
 output.</li>

 <li>The keyword arguments @(':on') and @(':off') may now take value
 @('nil').</li>

 <li>So-called ``on-off specs'', @('(:on-off sym1 ... symk)') are now allowed
 for keyword arguments @(':on') and @(':off'), which let you turn on or off all
 output types except the specified @('symi').  On-off specs are similarly
 supported for keyword arguments @(':summary-on') and @(':summary-off').</li>

 <li>There is a new keyword for @(tsee with-output), @(':ctx'), which supports
 a sort of global override of @(see event) contexts.  See @(see with-output)
 and see @(see ctx).</li>

 <li>There is better error checking, in particular for duplicate keywords.</li>

 </ul>

 <p>The value returned by a successful event @('(encapsulate ... ev_i
 ... ev_n)') is no longer always @('T').  See @(see encapsulate).</p>

 <p>Two event macros produce much less output than before, as follows.  Thanks
 to Alessandro Coglio for requesting these changes and to him and Eric Smith
 for helpful discussions.</p>

 <ul>

 <li>@(tsee Defstub) is not only quieter but also does a bit more
 error checking.</li>

 <li>@(tsee Defun-sk) has a new @(':verbose') argument for when output is
 desired after all.</li>

 </ul>

 <p>For the @(':logic') and @(':exec') components of a @(tsee defabsstobj)
 export, @(see signature)s no longer need to match.  Thanks to Sol Swords for
 suggesting this improvement.  Now, the only such requirements are that the
 lengths of the input signatures are equal and the lengths of the output
 signatures are equal.</p>

 <p>The utility @(tsee set-guard-checking) now prints messages to
 @('(standard-co state)') rather than to @('*standard-co*').  (Of course, these
 are the same by default.)</p>

 <p>In a proposed @(see linear) rule, hypotheses that are calls of @(tsee
 bind-free) are now accounted for when considering whether each of the
 @(':trigger-terms') has sufficient free variables (see @(see linear), in
 particular condition (b) there, and see @(see bind-free)).  Thanks to Dave
 Greve for reporting this issue.  The example below has the indicated failure
 in ACL2  Version 8.3 but is now accepted.</p>

 @({

 (defstub f (x) t)
 (defstub g (x) t)

 ; The following two events are the same except that the first supplies
 ; :trigger-terms while the second does not (instead computing trigger terms
 ; heuristically).  These should either both fail or both succeed; now they
 ; both succeed.

 ; FAILED, but now SUCCEEDS after the fix since then variables y and z are
 ; considered to occur (free) in the hypotheses when determining
 ; whether the hypotheses and trigger term include enough variables to cover
 ; those in the conclusion.
 (defaxiom ax1
   (implies (bind-free '((z . z))) ; or, (bind-free '((z . z)) (y z))
            (< (f x) (g y)))
   :rule-classes ((:linear :trigger-terms ((f x)))))

 ; SUCCEEDED even before the fix: the bind-free hypothesis fools ACL2
 ; into believing that otherwise-free variables may be bound by the
 ; bind-free alist.
 (defaxiom ax2
   (implies (bind-free '((z . z))) ; or, (bind-free '((z . z)) (y z))
            (< (f x) (g y)))
   :rule-classes :linear)

 })

 <p>The report for @(':')@(tsee brr) when a hypothesis fails to be relieved
 shows repeated attempts to bind free variables not only as before &mdash; that
 is, when a hypothesis has free variables &mdash; but also when the hypothesis
 is a call of @(tsee bind-free) that returns a list of substitutions.  Thanks
 to Dave Greve for bringing up this issue.</p>

 <p>It is now an error for a @(':')@(tsee linear) rule's conclusion to generate
 a polynomial whose terms are all determined to be non-numeric.  Thanks to Eric
 Smith for suggesting such a check.  Here is an example of such a rule that was
 formerly admitted but useless but now causes an error.</p>

 @({
 (defthm bad-rule
         (equal (< (foo x) x) nil)
         :rule-classes :linear)
 })

 <p>In executable code, calls of @(tsee hide) in @(tsee let)-bindings or @(tsee
 lambda) bodies are no longer considered to represent @(tsee ignore)
 declarations.  We thank Alessandro Coglio for raising and discussing this
 issue.  Below is a log, based on that discussion, that was produced using ACL2
 before this change.  After this change, the second and third calls of
 @(':')@(tsee trans) will now result in errors, as noted in comments below.
 Previously ACL2 treated the @('hide') calls in those two input expressions as
 though they represented @('ignore') declarations, in the sense of translation
 of the first form shown below.  That is still the case when translating for
 theorems rather than executable code; for details see the ``Essay on Using
 Hide for Ignored Let-bindings'' in the ACL2 source code.</p>

 @({
 ACL2 !>:trans (let ((x 0)) (declare (ignore x)) 1)

 ((LAMBDA (X) '1) (HIDE '0))

 => *

 ACL2 !>:trans ((LAMBDA (X) '1) (HIDE '0)) ; error after this change

 ((LAMBDA (X) '1) (HIDE '0))

 => *

 ACL2 !>(untranslate '((LAMBDA (X) '1) (HIDE '0)) nil (w state))
 (LET ((X (HIDE 0))) 1)
 ACL2 !>:trans (LET ((X (HIDE 0))) 1) ; error after this change

 ((LAMBDA (X) '1) (HIDE '0))

 => *

 ACL2 !>
 })

 <p>The @(tsee defabsstobj) keyword, @(':CONCRETE'), has been changed to
 @(':FOUNDATION').  Although the use of @(':CONCRETE') is still supported in
 this release (Version 8.4), it generates a warning that this usage is
 deprecated and will likely not be supported after this release.  Also,
 documentation and comments now typically speak of ``foundational stobj'' for
 the underlying stobj of the abstract stobj (which can be supplied explicitly
 by the @(':FOUNDATION') keyword) rather than ``corresponding concrete stobj'';
 this reflects the fact that the foundational stobj may itself be an abstract
 stobj (which is not new for this release).</p>

 <p>Strengthened error-checking for @(tsee stobj-let) to insist that if an
 updater is supplied explicitly in a binding, then it must be a valid updater.
 This check was formerly made only if the variable bound in that binding is
 among the producer variables (see @(see nested-stobjs)).  For example, the
 following now causes an error, but it was formerly accepted in spite of the
 fact that @('xyz') is not the updater for the accessor, @('top1-fld'); in fact
 @('xyz') is not even defined!</p>

 @({
 (defstobj sub1 sub1-fld1)
 (defstobj top1 (top1-fld :type sub1))
 (defun f1 (top1)
   (declare (xargs :stobjs top1))
   (stobj-let
    ((sub1 (top1-fld top1) xyz)) ; bad updater!
    (val)
    (sub1-fld1 sub1)
    val))
 })

 <p>The function symbol @('symbol<') replaces the function symbol
 @('symbol-<').  More generally, for every built-in function symbol and theorem
 name containing @('"SYMBOL-<"'), that string in its @(tsee symbol-name) is
 replaced by @('"SYMBOL<"').  The function @('logical-defun') is similarly
 replaced by @('get-defun-event').  Thanks to Alessandro Coglio for suggesting
 these changes.  Note that the old function names still work in ACL2 Version
 8.4, as they are macro-aliases for the corresponding new function names (see
 @(see add-macro-alias)); however, they are deprecated and will probably not be
 supported in later ACL2 versions.  (A deprecation warning is printed each time
 one of those macros is expanded.)</p>

 <p>The keyword @(':witness-dcls') of @(tsee defun-sk) is deprecated and will
 probably be unsupported in future ACL2 releases.  Use @(tsee declare) forms
 instead; see @(tsee defun-sk).</p>

 <h3>New Features</h3>

 <p>It is now possible to assign @(tsee badge)s to @(':')@(tsee program) mode
 functions, which allows them to be used by @(tsee apply$), @(tsee lambda$) and
 @(tsee loop$) during top-level evaluation.  See @(tsee defbadge), which
 assigns badges but not @(see warrant)s and which can handle both @(':')@(tsee
 program) and @(':')@(tsee logic) mode functions.</p>

 <p>A new option for @(tsee certify-book), provided with keyword option
 @(':useless-runes') or environment variable @('ACL2_USELESS_RUNES'), makes it
 possible to speed up repeated certification of a book, sometimes
 substantially.  See @(see useless-runes).  Thanks to Sol Swords for reporting
 a bug (in ACL2 source function @('read-file-iterate-safe')) and supplying a
 fix, which we have incorporated.  Also thanks to Eric Smith for requesting
 that each tuple in a generated ``useless-runes'' file be printed on a single
 line starting after a space, thus supporting grep-like tools.  Finally, thanks
 to Alessandro Coglio and Eric Smith for discussions leading to creation of
 @('.sys/') subdirectories to hold useless-runes files.</p>

 <p>A new keyword for @(tsee defstobj), @(':non-executable'), can be given
 value @('t') to skip memory allocation for the new @(see stobj), by avoiding
 creation of a ``live'' (mutable) stobj.  See @(see defstobj).  Thanks to
 Warren Hunt for encouraging development of this feature.</p>

 <p>The rewriter now rewrites the bodies of certain quoted @(see lambda)
 objects.  However, some restrictions apply.  See @(see rewrite-lambda-object).
 In addition some new lemmas and a new metafunction have been added to the book
 @('projects/apply/top'), which users are still encouraged to include in
 sessions dealing with @(tsee apply$).  The new metafunction is named
 @('relink-fancy-scion') and can also cause @('lambda') objects to be
 transformed.  See the discussion of that metafunction in @(see
 rewrite-lambda-object).</p>

 <p>Added @(tsee toggle-inhibit-warning) and @(tsee toggle-inhibit-warning!) to
 add or delete a warning string from the @('inhibit-warnings-table'), rather
 than setting that entire table as is done by @(tsee set-inhibit-warnings).</p>

 <p>It is now possible to instruct the prover to respect requests to @(see
 disable) the @(see definition) of the primitive, @(tsee mv-nth), rather than
 continuing to expand that definition.  See @(see theories-and-primitives), in
 particular the note for advanced users at the end of that topic.  Thanks to
 Alessandro Coglio for requesting this feature.</p>

 <p>A new utility, @(tsee memoize-partial), allows memoization for functions
 that were admitted by adding a formal parameter that decreases on each
 recursive call (sometimes called a ``limit'' or a ``clock'').  Normally that
 extra parameter can severely impede the utility of memoization; however, the
 function actually executed does not have that extra parameter.  This allows
 for more memoization hits.  Thanks to Mertcan Temel for an inquiry leading to
 this enhancement, and for helpful discussions.</p>

 <p>A new rule-class (see @(see rule-classes)) has been added, named
 @(':')@(tsee rewrite-quoted-constant).  Rules in this class can cause the
 rewriter to replace one quoted constant by an equivalent one under a given
 @(see equivalence) relation.  See @(see rewrite-quoted-constant).</p>

 <p>The @(tsee loop$) parser produces more informative error messages on
 ill-formed @('loop$') statements.</p>

 <p>A new @(tsee memoize) keyword, @(':invoke'), supports the replacement of
 calls of one function by another.  In that sense it is similar to @(tsee
 defattach); the difference is that with @('(memoize f :invoke g)'), it is
 necessary first to prove the equality of @('f') and @('g'); therefore, ACL2
 will compute calls of @('f') by calling @('g') even during proofs.  In
 particular, the tool @(see add-io-pairs) is built on top of this capability;
 it allows evaluating a function call by fast lookup of a verified input-output
 pair.  Thanks to Eric McCarthy, Alessandro Coglio, and Eric Smith for
 requesting the latter capability and providing helpful feedback.</p>

 <p>A new @(see xargs) keyword for @(tsee defun), @(':type-prescription'), can
 be supplied as a formula in the shape of a @(see type-prescription) rule.  It
 is checked to be implied by the built-in type-prescription rule computed for
 the newly-defined function.  Thus, it can serve as documentation for the
 expected type returned by the function; if the implication is not equivalence,
 a warning is printed.  Thanks to Alessandro Coglio and Eric Smith for the
 suggestion.</p>

 <p>@(see Table)s may now supply custom error messages for table @(':guard')
 failures.  This is accomplished by supplying a table @(':guard') that returns
 two values instead of one.  For a return @('(mv okp msg)'), if @('okp') is
 non-@('nil') then the table guard is considered to be true, that is, it has
 the same meaning as a non-@('nil') single-value return.  Also, @('(mv nil
 nil)') has the same meaning and effect as a @('nil') single-value return: the
 table guard fails, and a generic error message is printed about the illegal
 key/value pair.  The new case is a return of @('(mv nil msg)'), where @('msg')
 should be a @(tsee msgp) &mdash; a string or a cons suitable for printing with
 the @(tsee fmt) directive, @('~@').  In that case, @('msg') is printed (using
 the @(tsee fmt) directive, @('~@')) instead of a generic error message.  This
 new feature is now used in some built-in tables.  See @(see table).</p>

 <p>The @(see proof-builder) command @(tsee type-alist) has a new optional
 argument that supports printing the type-alist in an alist format.  Thanks to
 Mihir Mehta for requesting this feature.</p>

 <p>A new summary type, @('REDUNDANT'), controls whether a message is printed
 indicating a redundant event (see @(see redundant-events)), which however will
 still always take place if @('EVENT') output is not inhibited (see @(see
 set-inhibit-output-lst)).  See @(see summary).</p>

 <p>A @('defabsstobj') event may now specify child @(see stobj) fields, for use
 by @(tsee stobj-let).  See @(see defabsstobj), and see @(see community-books)
 file @('books/system/tests/abstract-stobj-nesting/README') for a brief guide
 to the examples in that directory.  Thanks to Sol Swords for requesting this
 feature and helping to design it, as well as for his helpful discussions,
 feedback, and test files.</p>

 <p>The @(':congruent-to') keyword is now supported for @(tsee
 defabsstobj).</p>

 <p>@(tsee Stobj-let) now allows aliases in the bindings in some cases where
 this is safe because updating is not involved.  Thanks to Sol Swords for
 suggesting such a change.</p>

 <p>Added a function @(tsee ctxp) to recognize valid contexts, which are used
 for printing error message (see @(see ctx)).  Thanks to Eric Smith for
 requesting this addition and to Alessandro Coglio for suggesting that it be
 disabled, for efficiency.</p>

 <p>The utilities @(tsee brr) and @(tsee monitor) now each take an optional
 argument that avoids output.  A new utility, @(tsee monitor!), is a
 combination of these two with their new optional arguments of @('t'), thus
 also avoiding output.  Thanks to Eric Smith for requesting a version of
 @('monitor') that turns on @('brr').</p>

 <p>A new utility, @(tsee get-guard-checking), returns the @(see
 guard)-checking value most recently installed, either @('t') (when the ACL2
 executable was built) or presumably by @(tsee set-guard-checking).  Thanks to
 Eric McCarthy for suggesting this utility.</p>

 <p>The function @(tsee aset1-trusted) may be used in place of @(tsee aset1) to
 avoid @(see invariant-risk), but is therefore @(see untouchable).</p>

 <p>Added a new utility, @(tsee print-object$+), that is like @(tsee
 print-object$) but instead of taking @('STATE'), @(tsee print-object$+) is a
 macro that takes keyword arguments to customize the output.  See @(see
 print-object$+).  Thanks to Eric Smith for requesting such additional print
 control.</p>

 <h3>Heuristic and Efficiency Improvements</h3>

 <p>We changed the lightweight ``preprocess'' simplifier for ``@(see simple)''
 rules in the prover's @(see waterfall), in the case that the term is the
 application of a defined function symbol to constant (quoted) arguments.  As
 before, if the @(see executable-counterpart) rule for that function symbol is
 @(see enable)d, then the call is evaluated in Lisp; and if that evaluation
 fails (typically because a constrained function is called), then an attempt is
 made to rewrite the term by applying a @(see simple) rule.  The change is for
 how failure is handled, that is, in the case that evaluation fails and the
 term is not rewritten.  Formerly, the term was surrounded by a call of @(tsee
 hide).  Now, that is only done by the main rewriter, not by the ``preprocess''
 simplifier.  Thanks to Eric Smith for a communication on the acl2-help list,
 on a thread started by Mark Greenstreet, that led us towards making this
 change.  Mark's failed proof now succeeds after this change, but here is a
 simpler example.  Formerly, the commented-out @(':do-not') hint was required
 for the proof of the @(tsee thm) call below to succeed, because the definition
 of @('g') is not simple and hence the ``preprocess'' simplifier replaced @('(g
 3)') by a term @('(hide (comment ...) (g 3))') before the rewriter could apply
 the definition of @('g').</p>

 @({
 (defstub f (x) t)
 (defun g (x) (cons x (f x)))
 (thm (equal (car (g 3)) 3)
      ;; :hints (("Goal" :do-not '(preprocess)))
      )
 })

 <p>The ACL2 rewriter has a ``being-openedp'' heuristic that prevents loops, by
 saving a stack based on what is currently being rewritten.  This can prevent
 the use of a @(see definition) or @(see rewrite) rule.  Now the heuristic is
 turned off when the term's function symbol has a non-recursive definition and
 simplification has just settled down (see @(see hints-and-the-waterfall)).  To
 restore the old behavior, i.e., to use the heuristic in all cases &mdash; thus
 providing backward compatibility when a proof fails &mdash; evaluate the form:
 @('(defattach-system being-openedp-limited-for-nonrec
 constant-nil-function-arity-0)').</p>

 <p>When a command executed in a logical @(see world), @('w'), is interrupted,
 the world is reverted to @('w').  That reversion process could be very slow if
 the interrupt was taken during the installation of the new world, as indicated
 by the messages:</p>

 @({
 Flushing current installed world.
 Reversing the new world.
 Installing the new world.
 })

 <p>That process has been sped up significantly.  Moreover, the new process
 avoids a bug reported by Eric Smith, who we thank for sending an example of
 how the process was interacting badly with @(tsee reset-prehistory).  Code
 implementing that interaction was introduced in Version  4.0 to speed up the
 process; that code has been eliminated, as it is no longer necessary.</p>

 <p>ACL2's @(see type-set) reasoning has been slightly strengthened to
 comprehend Boolean combinations of strong @(see compound-recognizer) calls on
 a single variable when building a context (a so-called @(see type-alist)).
 (By a ``strong compound-recognizer call'' we mean a unary function that
 recognizes a union of primitive ACL2 types and has, either explicitly or
 implicitly, a corresponding @(see compound-recognizer) rule; examples include
 @(tsee stringp), @(tsee integerp), and @(tsee true-listp).)  In particular,
 this change can strengthen the result of @(see forward-chaining).  Thanks to
 Eric Smith, who raised this issue by providing an example that we include in a
 comment, inside the form @('(defxdoc note-8-4 ...)') in @(see community-book)
 @('books/system/doc/acl2-doc.lisp').</p>

 <p>@(csee Type-set) reasoning also has been improved for inequalities to take
 more advantage of the fact that the number 1 constitutes a singleton type.
 For example, after evaluating @('(defstub foo (x) t)') ACL2 is now able to
 prove @('(implies (< 2 x) (equal (foo (bitp x)) (foo nil)))') where previously
 it could not.  In fact @('2') can now be replaced by any rational number that
 is at least 1.</p>

 <p>The function @(tsee compress1) has been made more efficient in the
 following ways.</p>

 <ul>

 <li>@('Compress1') is now faster when the @(':ORDER') specified by the given
 @(see array)'s @(see header) is @('<') or @('>') and the alist is properly
 ordered: header first, then ascending (for @(':ORDER <')) or descending (for
 @(':ORDER >')) order of indices, with no value in the alist equal to the
 @(':DEFAULT') specified by the header.  In particular, this can cut the time
 to run @('compress1') on an alist containing only the header by more than
 half, which addresses a request made by Eric Smith (whom we thank for bringing
 this efficiency issue to our attention).</li>

 <li>For the change noted just above, Eric also noticed that when the @(see
 default) is @('nil') then there was no speedup.  This led us to fix an
 existing bug (technical description: for an array with default @('nil'), the
 alist was never considered to be in order).</li>

 <li>Functions @(tsee compress1) and @(tsee compress2) no longer require the
 new and old dimensions to agree in order that the underlying raw lisp array is
 reused.  Now it suffices for the new dimension (for @('compress1'); each
 dimension for @('compress2')) to be at least as great as the old.
 (You can still avoid reuse of the raw Lisp array by using @(tsee
 flush-compress).)  Thanks to Eric Smith for suggesting this change.</li>

 </ul>

 <p>We found that @(tsee accumulated-persistence) was measurably slowing down
 ACL2 even when it is off.  We modified its implementation and measured a time
 reduction of 3.7% for a proof-intensive book.  The modification includes a
 documented efficiency tweak to @(tsee wormhole-eval).</p>

 <p>The @(see linear-arithmetic) heuristics have long taken advantage of
 negated equality hypotheses.  These heuristics have been strengthened to take
 further such advantage.  Thanks to Warren Hunt for sending an example proof
 attempt that failed before this change but now succeeds, and for his
 encouragement to pursue an improvement to linear arithmetic that can benefit
 such proof attempts.</p>

 <p>The removal of @(see guard-holders) has been augmented to include removal
 of certain ``trivial'' lambda applications.  See @(see guard-holders), in
 particular for how to restore the legacy behavior.  Thanks to Alessandro
 Coglio for an example and Eric Smith for a subsequent suggestion that led to
 this enhancement.</p>

 <h3>Bug Fixes</h3>

 <p>A soundness bug, present since @(tsee loop$) was introduced, was fixed. The
 bug was manifested when the keyword @(':guard') was used as the @('loop$')
 body, as in @('(loop$ for v in lst collect :guard)').  (Note: It's not clear
 that this bug could be used to prove @('nil').)</p>

 <p>A soundness bug was fixed by changing @(tsee defabsstobj) to avoid using
 @(tsee mbe) in the definitions generated for the logic.  The problem was that
 the @(':logic') and @(':exec') forms are not actually equal (they correspond,
 in the sense of the correspondence predicate), and this can be exploited by
 using a @(':')@(tsee guard-theorem) @(see lemma-instance).  For an example
 proof of @('nil') in Version 8.3, see a comment about a @('defabsstobj') bug
 in the form @('(defxdoc note-8-4 ...)') in file
 @('books/system/doc/acl2-doc.lisp').</p>

 <p>A soundness bug was fixed in the functions that print to strings, such as
 @('fmt-to-string'); see @(see printing-to-strings).  The bug was a dependence
 of the result on the ACL2 @(see state), even though @('state') is not an
 argument to these functions.  More specifically, the dependence was on the
 @(tsee current-package) and the global @(tsee evisc-table).  For examples see
 @(see community-books) @('books/system/tests/fmt-to-string.lisp') and
 @('books/system/tests/fmt-to-string-pkg.lisp').  Note: We also strengthened
 the @(see guard)s on these functions to require that the keys of the
 @('fmt-control-alist') alist argument are all appropriate; in particular, the
 symbol @('current-package') in the @('"ACL2"') package is a suitable key,
 but for example the keyword @(':current-package') is not.</p>

 <p>It was possible to prove @('nil') by counterfeiting @('record-expansion')
 calls, which are normally only created by the implementation in support of
 @(tsee make-event) calls.  This soundness bug has been fixed.  (The bug was
 perhaps impossible to hit in ordinary usage, where @('record-expansion') is
 not used explicitly.)  A proof of @('nil') before this fix may be found in a
 comment in ACL2 source function, @('corresponding-encaps').</p>

 <p>The mechanism for tracking @(see warrant)s needed during a proof had a bug,
 which might be a soundness bug if one uses @(tsee apply$) or @(tsee loop$).
 That bug has been fixed.</p>

 <p>Fixed a bug that was preventing use of the RDTSC hardware instruction in
 SBCL on most x86-based platforms, and possibly erroneously attempting to make
 use of that instruction on some other platforms.  Thanks to Keshav Kini for a
 query that led to this fix.  Also restricted RDTSC to x86-based platforms,
 thanks to a suggestion by Curtis Dunham, to enable Arm builds of ACL2.</p>

 <p>The use of @(tsee apply$) on calls of @(tsee if) no longer cause raw Lisp
 errors.  (The same is true for calls of the subroutine @('apply$-prim') of
 @('apply$').)  For example, these calls now evaluate without error: @('(apply$
 'if '(nil nil nil))') and @('(apply$-prim 'if '(nil nil nil))').</p>

 <p>We made the following fixes to the @(tsee accumulated-persistence)
 utility.</p>

 <ul>

 <li>Applications of @(see type-prescription) rules that were erroneously
 labeled as ``useless'' are now appropriately labeled as ``useful''.</li>

 <li>The documentation for @(tsee accumulated-persistence) now correctly states
 that the form @('(accumulated-persistence-oops)') undoes the clearing effect
 of @('(accumulated-persistence t)'), rather than of
 @('(accumulated-persistence nil)').</li>

 <li>Uses of @(see definition) rules because of @(':')@(tsee expand) hints,
 either explicitly given by the user or generated by ACL2's heuristics for doing
 induction, were not being recorded by @(tsee accumulated-persistence).  They
 are now.</li>

 </ul>

 <p>Fixed a bug that was causing books to be included as ``uncertified'' after
 their certification stored checksums (see @(see book-hash)).  Thanks to Keshav
 Kini for reporting this bug.</p>

 <p>ACL2 could occasionally simplify subterms of a call of @(tsee hide) even
 without any applicable rules or @(':expand') @(see hints).  (Technical note:
 the problematic source function was @('normalize').)  We considered this to be
 a bug, so it has been fixed.</p>

 <p>The notion of redundancy for @(tsee defstobj) @(see events) was too weak,
 as evidenced by the following example.  Consider the following book, named
 @('"bug.lisp"').</p>

 @({
 (in-package "ACL2")
 (defstobj st fld)
 (defun foo (st) (declare (xargs :stobjs st)) (fld st))
 })

 <p>After certifying this book, a raw Lisp error could occur after evaluating
 the following forms, because the compiled definition of @('foo') from
 including the book referenced a function, @('fld'), which is now a macro.</p>

 @({
 (defstobj st fld :inline t)
 (include-book "bug") ; The defstobj event in this book is redundant here.
 (foo st)
 })

 <p>The bug has been fixed by requiring a redundant @(tsee defstobj) event to
 be syntactically identical to the pre-existing corresponding @(tsee defstobj)
 event.</p>

 <p>A raw Lisp error would occur when the value of an @(':')@(tsee
 instructions) hint is not a true (null-terminated) list.  ACL2 now produces an
 informative error message in that case.</p>

 <p>Improved @(':')@('print-gv') to do its computation in the ACL2 @(see world)
 in which the @(see guard) violation took place.  See @(see print-gv); in
 particular, that topic concludes with a discussion of this issue.  Thanks to
 Eric Smith for reporting this issue along with a simple example.</p>

 <p>The following @(tsee defun-sk) bugs were fixed.</p>

 <ul>

 <li>The @(see guard) was being ignored (that is, treated as @('t')) when
 @(':constrained t') was specified in a @('defun-sk') event.  Thanks to
 Alessandro Coglio for reporting this bug.</li>

 <li>@(tsee Defun-sk) could fail when the formal parameters include @(see
 stobj)s or @('state').</li>

 <li>@(tsee Defun-sk) provided no direct way to allow formals to be ignored.
 Now, @('ignorable') @(see declaration)s are permitted.</li>

 </ul>

 <p>For Lisps that do not compile on the fly (that is, Lisps other than CCL and
 SBCL), evaluation of @(':comp t') effectively unmemoized functions that were
 not already compiled.  This has been fixed.</p>

 <p>When a @(see stobj) hash-table's ``init'' function was called with size 0,
 an error could occur for host Lisp GCL, complaining that size 0 is not allowed
 for hash-tables.  This has been fixed by using size 1 instead of 0 in this
 case.</p>

 <p>Reporting by @(see break-rewrite) has been fixed for cases when failure is
 due to a hypothesis with a @(see backchain-limit) of 0.  There were actually
 two such bugs: one due to improper handling of @(see linear) rules (which
 might have occurred even for other backchain-limits besides 0), and one due to
 the erroneous assumption that backchaining has only just begun at the point of
 failure.  Thanks to Mihir Mehta for sending an example that exhibited both
 bugs.  A discussion of the second bug, including a simple example, may be
 found in a comment in the ACL2 source function,
 @('tilde-@-failure-reason-phrase1-backchain-limit').</p>

 <p>@(':OR') @(see hints) that contain a single list (which satisfies @(tsee
 keyword-value-listp)) were being mishandled.  This has been fixed.  Thanks to
 Dave Greve who sent an example @(tsee defthm) event specifying
 @(':hints (("Goal" :or ((:in-theory (e/d () ()) :nonlinearp t))))'), which
 formerly caused a Lisp error.</p>

 <p>Fixed a bug in tracking the @(see cbd) that could cause failures of @(tsee
 include-book) in raw-mode.  Thanks to Warren Hunt for a query leading to this
 fix.</p>

 <p>Fixed a bug that was preventing some deep @(see patterned-congruence) rules
 from being applied.  This could occur when on the left-hand side, the outermost
 function symbol is the same as the next function symbol going in towards the
 variable that differs on the right-hand side.  Thanks to Mihir Mehta for
 reporting this bug and including a replayable example.</p>

 <p>Fixed several issues with @(tsee fmt) (and related printing utilities)
 pertaining to linebreaks.  These include the following, many of which are
 illustrated in a new file, @('system/tests/fmt-tests-input.lsp') (search there
 for ``2020'').</p>

 <ul>

 <li>A space past the @(tsee fmt-soft-right-margin) now results in a linebreak
 even in the case of tilde-space (`@('~ ')').</li>

 <li>As before, for punctuation after a tilde-x (`@('~x')') directive, ACL2
 avoids printing in column 0 after a linebreak.  This desirable behavior now
 extends to the case that `@('~x')' is inside a tilde-atsign (`@('~@')')
 directive.  For example, after @('(set-fmt-hard-right-margin 10 state)') try
 either @('(fmx "~@0." (msg "~x0" '(ab de gh)))') or (fmx
 "~#0~[~x0~/~x0~]." '(ab de gh)).</li>

 <li>Spaces are respected after tilde-y (`@('~y')') directives.  For example,
 @('(cw "~y0 A~%" 3 4)') now prints the letter @('A') in column 2 rather than
 column 0.  Thanks to Eric Smith and Alessandro Coglio for suggesting this
 change.</li>

 <li>An extra character is sometimes permitted before deciding that a tilde-x
 (`@('~x')') directive causes a linebreak.</li>

 <li>Tilde directives that cause no printing are often ignored when deciding
 whether to keep a punctuation mark with a pretty-printed expression.  For
 example, when setting both right margins (soft and hard) to 10, the following
 no longer prints a comma in column 0: @('(fmx "~x0~@1, more~%"
 'aaaaaaaaaa "")').</li>

 <li>Fixed a @(tsee double-rewrite) warning, which was breaking the word
 ``is''.  Thanks to Mihir Mehta for pointing this out.</li>

 </ul>

 <p>After setting @(see state) global @('trace-co'), for example with
 @('(f-put-global 'trace-co (@ standard-co) state)') (say, after setting
 standard-co to an open output channel), printing of the trace level such as
 ``@('1>')'' and ``@('<1')'' will now go to that channel.  Formerly, this could
 fail after setting @('trace-co') directly rather than using @(tsee
 open-trace-file).</p>

 <p>There are improvements to @(tsee certify-book) and @(tsee include-book),
 which pertain to the loading of compiled files by @('include-book') before
 events in the book are processed.  That process supports preservation of @(see
 hons)es and @(see fast-alists), and reporting of ``stolen'' alists (see for
 example @(see with-stolen-alist)).  Relevant tests, with implementation-level
 comments, may be found in the new @(see community-books) directory,
 @('books/system/tests/early-load-of-compiled/').  Thanks to Sol Swords for
 helpful discussions.</p>

 <p>Improved a utility that builds sets of clauses, which improves the
 reliability of using a @(see lemma-instance) of the form @('(:guard-theorem
 <name> nil)').  Thanks to Eric Smith for reporting this problem with a simple
 example, and to Dave Greve for following up with a related example; both now
 work as one would expect.</p>

 <p>Fixed printing of the ACL2 @(see state) in error messages, specifically
 when executing a non-executable function.</p>

 <p>Fixed a bug that could cause a raw Lisp error when processing a @(see
 linear) rule with a @(tsee bind-free) hypothesis, when that hypothesis does
 not specify a list of variables (in its second argument).  Thanks to Dave
 Greve for reporting this bug by sending a simple example.  (Technical note:
 the fix was in the definition of source function all-vars-in-hyps.)</p>

 <p>For @(tsee defabsstobj), a suitable error now occurs when the @(':LOGIC')
 version of an abstract @(see stobj) export has the foundational stobj as a
 formal parameter that is declared as a @(see stobj).  Formerly, a confusing
 hard error could occur in this case.</p>

 <p>An unfortunate ``Proof skipped'' could be printed during the
 @('include-book') phase of @(tsee certify-book) for certain uses of @(tsee
 make-event), including calls of @(tsee thm).  This has been fixed.</p>

 <p>Fixed an implementation error that was being reported when a @(tsee
 stobj-let) form updates two array fields each with at least two indices that
 are not all natural numbers.  For an example that caused this error, see @(see
 community-book) @('books/system/tests/nested-stobj-two-updates.lisp').</p>

 <p>Fixed a bug in resizing @(see stobj) arrays whose elements are specified to
 be @('(signed-byte 30)') or a subtype of that type.  Thanks to Eric Smith for
 reporting this bug with a reproducible example.</p>

 <p>For a @(tsee stobj-let) call occurring in other than a definition body, the
 top-level bindings of variables to child stobj accessors was treated as @(tsee
 let*) rather than as @(tsee let).  That was at odds with the documentation,
 and has been fixed.</p>

 <p>Fixed a bug that caused an error when attempting to redefine a function for
 which a @(':')@(tsee COMPOUND-RECOGNIZER) rule has been proved.  Thanks to
 Eric McCarthy for reporting this bug (GitHub Issue #1273) with a reproducible
 example.</p>

 <p>Raw mode now does a better job of maintaining global @(see stobj) values.
 Here is an example that illustrates the fix; also see @(see set-raw-mode),
 which has been extended to explain a related but remaining issue.</p>

 @({
 (defstobj st2 (ar :type (array t (8)) :resizable t))
 (set-raw-mode-on!)
 (resize-ar 20 st2)
 (ar-length st2) ; formerly 8, but now 20 as expected
 })

 <p>For any @(tsee proof-builder) command of the form @('(= term1 term2 atom
 ...)'), the keyword arguments were ignored.  This has been fixed, and also the
 documentation for @(tsee acl2-pc::=) has been improved.</p>

 <p>Consider when a @(see community-book) is included using an ACL2 executable
 different from the one that certified the book, with those two executables
 being located in different directories.  The book is now considered to be
 uncertified in that case.  To avoid this issue see @(see include-book) for a
 discussion of environment variable @('ACL2_SYSTEM_BOOKS').</p>

 <h3>Changes at the System Level</h3>

 <p>(SBCL only) Filenames are now read as ASCII (specifically, ISO-8859-1) when
 the host Lisp is SBCL, which formerly was not the case.  Thanks to Stephen
 Westfold for suggesting this change.</p>

 <p>ACL2 can once again be built on CMU Common Lisp (CMUCL) (though we have
 only done minimal testing).  The problem turned out to be with ACL2, not
 CMUCL: low-level Lisp code in the ACL2 sources was destructively modifying a
 quoted constant.  (For implementation details, see @('*fncall-cache*') in
 source file @('translate.lisp').)  The bug was discovered when considering
 modification of the build process to compile ACL2 source files when the host
 Lisp is SBCL.  Thanks to Stas Boukarev for pointing us in the right direction
 to debug this error.</p>

 <p>There is now a way to save the untranslated bodies of built-in @(':')@(tsee
 program) mode functions.  WARNING: This is not officially supported!  But it
 may be useful for tools such as a linter.  See @('GNUmakefile'): search there
 for @(':acl2-save-unnormalized-bodies'), where you will see that a more
 general capability is actually available for evaluating forms before the build
 begins.  Thanks to Eric Smith for correspondence leading to this
 enhancement.</p>

 <p>Starting with ACL2 Version 7.0, the availability of hash consing (see
 @(tsee hons)) and the other features described in @(see hons-and-memoization)
 have been part of a default ACL2 build; meanwhile, support for ``classic''
 ACL2 has essentially been discontinued.  These features require a certain Lisp
 action (implementation note: pushing @(':hons') onto @('*features*')) that had
 been done during the ACL2 build by the `@('make')' process (with code in
 @('GNUmakefile')).  Now that action is taken unconditionally in the ACL2
 source code.  Thanks to Petter Gustad for reporting an error when attempting
 to build ACL2 without using `@('make')'; this change should fix that bug.
 With this change you can no longer attempt to build ``classic'' ACL2(c)
 without editing ACL2 source file @('init.lisp'); environment variable
 @('ACL2_HONS') no longer has any effect.  (On a related technical note: An
 obscure feature @(':memoize-hack') seems not to be used anywhere, and has been
 eliminated.)</p>

 <p>(SBCL only) Handling in ACL2 of the SBCL ``read-cycle-counter'' has been
 modified to reflect its handling in recent SBCL versions (starting around late
 2018 or early 2019).  This avoids an ACL2 build error on some platforms.
 Thanks to John R. Strohm for reporting such a problem (on a Raspberry Pi).</p>

 <p>(SBCL only) Increased the number of special variables that can be created,
 which allowed community book
 @('books/kestrel/apt/schemalg-template-proofs.lisp') to certify.</p>

 <p>Fixed builds that use a relative pathname for the LISP environment
 variable (for host Lisps CCL, SBCL, Allegro CL, and CMUCL; GCL and LispWorks
 didn't seem to have this problem).  Thanks to Mihir Mehta for bringing this
 issue to our attention; and thanks to Andrew Walter for reporting a problem
 with our first solution for SBCL and proposing an alternative, which we
 adopted.</p>

 <p>Fixed the process for running ACL2 without building an executable image.
 Some initialization that was missing from that process is now included.  Also,
 added the missing command, (lp), to the instructions in section ``Running
 Without Building an Executable Image'' on the ``Obtaining and Installing
 ACL2'' web page (accessible from the ``Obtaining, Installing, and License''
 link on the ACL2 home page).  Thanks to Petter Gustad for an inquiry leading
 to these improvements.</p>

 <p>When invoking `@('make')' to build the ACL2 executable, output from the
 build process is now written to file @('make.log').  The terminal output is
 now minimal.  If there is already a file @('make.log'), it is first moved to
 @('make.log.bak').  See file @('GNUmakefile') for additional documentation.
 Thanks to Alessandro Coglio and Eric Smith for suggesting this change, and to
 David Rager for pointing out associated changes to make for Jenkins
 builds.</p>

 <p>The startup banner now has a cleaner look (see @(see startup-banner)).
 Thanks to Alessandro Coglio and Eric Smith for key suggestions for
 improvement.</p>

 <p>(CCL only) When an attempt to build ACL2 fails, a more informative error
 message is printed when the error is caused by invoking CCL as a soft link on
 the Unix PATH rather than as a regular file.  Thanks to Mertcan Temel for
 feedback leading to this change.</p>

 <p>A script @('bin/acl2') has been added below the main ACL2 directory.  It
 may be used in place of @('saved_acl2'), invoked from any directory.  If the
 @('bin') subdirectory is on one's Unix @('PATH') then of course @('acl2') will
 invoke this script (unless a different @('acl2') is in a directory that is
 earlier on that path).  Thanks to Alessandro Coglio for suggesting that an
 @('acl2') script be made available with ACL2, and to him and Eric Smith for
 subsequent discussions on that topic.</p>

 <p>When an error occurs while loading an @(see acl2-customization) file, ACL2
 quits with exit code 1.  Thanks to Eric Smith for suggesting the quit and to
 Eric McCarthy for suggesting exit code 1 in that case.</p>

 <p>ACL2 now does a more thorough job of doing proofs when ``@('make proofs')''
 is executed.  In particular, proofs were formerly skipped but are now
 performed for @(tsee defun) forms containing the explicit @(tsee xargs) @(see
 declaration), @(':mode :logic'), and for @(tsee defthm) events evaluated with
 @(see default-defun-mode) @(':logic') outside the so-called ``pass 2
 files''.</p>

 <h3>EMACS Support</h3>

 <p>The @(see acl2-doc) search commands (`@('s')' and `@('S')') were seen to
 use all available memory on a linux system, during the process of initializing
 the @('acl2-doc-search') buffer that is used for doing the searching.  That
 problem has been solved: that buffer is now loaded from a file that is built
 by the manual-building process and is downloaded by the acl2-doc `@('D')'
 command.</p>

 <p>Highlighting in lisp-mode (inside Emacs) has been improved, both by
 recognizing more keywords and by highlighting of some new arguments, in
 particular the first argument of @('defthm').  Thanks to Vivek Ramanathan,
 both for pointing out the @('defthm') issue and for suggesting code that was
 incorporated into the changes.</p>

 <p>The @(see acl2-doc) browser now queries when first loading an ACL2+books
 manual if you have a newer web-based version.  A ``yes'' response will use
 the (out-of-date) manual, while a ``no'' response will generally produce a new
 query asking if you want to download the manual from the web.  This change was
 made in support of building the manual more quickly, as the acl2-doc manual is
 no longer built by default.  See @(see acl2-doc) for how to do that build and
 other details.  Thanks to Alessandro Coglio, Eric Smith, and Sol Swords for
 discussions about speeding up the build of the manual.</p>

 <p>Fixed certain hangs in the @(see acl2-doc) browser.  For example, when
 standing on whitespace near the left margin of topic @(see *acl2-exports*),
 the '@('g')' command could formerly hang.</p>

 <h3>Experimental Versions</h3>

 <p>ACL2(p) now runs much more reliably on host Lisp SBCL (by taking advantage
 of a locking mechanism provided by SBCL).  Thanks to David Rager for providing
 this improvement.</p>

 <p>In ACL2(p), @(tsee set-waterfall-parallelism) no longer causes an error
 when there are @(tsee override-hints) if the argument is the existing value of
 the @(see state) global, @(''waterfall-parallelism'), or upon a transition of
 @(see waterfall-parallelism) to @('nil').  Thanks to David Rager for raising
 this issue (see GitHub Issue #1171) and discussing its resolution.</p>

 ")
other
(defxdoc note-8-5
  :parents (release-notes)
  :short "ACL2 Version  8.5 (July, 2022) 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 8.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-5-books) for a summary of changes made to the ACL2 Community Books
 since ACL2 8.4, including the build system.  Also note that with each release,
 it is typical that the value of constant @(tsee *acl2-exports*) has been
 extended, and that 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>Weakened hypotheses from built-in theorems (thus strengthening them)
 @('symbol-equality'), @('true-listp-first-n-ac-type-prescription'),
 @('ordered-symbol-alistp-getprops'), @('add-pair-preserves-all-boundp'), and
 @('symbol<-asymmetric').  Eliminated built-in theorem
 @('main-timer-type-prescription') entirely (that rule was already deduced by
 ACL2 at definition time).  Simplified guards slightly for built-in functions
 @('serialize-write-fn') and @('serialize-read-fn').  Thanks to Eric Smith for
 correspondence, based on his linter, leading to these improvements.</p>

 <p>The utility @(tsee without-evisc) formerly always (or nearly always)
 returned the @(see error-triple) @('(mv nil :invisible state)') after printing
 the result.  Now it generally returns @('(mv t nil state)') when evaluation of
 the given form causes an error.  See @(see without-evisc).  Thanks to Karthik
 Nukala and Eric Smith for reporting the former (undesirable) behavior.</p>

 <p>One would get an error when including an uncertified book when a
 @(':type-prescription') specified in an @(tsee xargs) @(see declaration)
 failed a validity check, even when no such failure occurs when that book is
 certified.  (That could happen because type-prescription information from
 locally included books is saved in the book's @(see certificate) file and is
 used when checking such @(':type-prescription') declarations.)  This situation
 now generates a warning rather than an error.  Thanks to Karthik Nukala and
 Eric Smith for sending an example that pointed out this problem.</p>

 <p>Output from @(':')@(tsee oops) may now be inhibited as @('OBSERVATION')
 output, by using @(tsee set-inhibit-output-lst) or @(tsee with-output).</p>

 <p>@(csee Raw-mode) has been fixed so that reasonable results are printed when
 multiple values are returned by a function defined in raw-mode or raw Lisp
 (rather than in the logic).  The following examples illustrate the problem and
 the fixed behavior.  The utilities @('add-raw-arity') and
 @('remove-raw-arity') are no longer necessary (and they had no effect anyhow,
 at least in recent ACL2 versions), so they have been removed.</p>

 @({
 (defstobj st fld)
 (set-raw-mode-on!)
 (defun f1 (st) st)
 (f1 st) ; printed a vector; now prints <st>
 (defun f2 (state) state)
 (f2 state) ; printed ACL2_INVISIBLE::|The Live State Itself|;
            ; now prints <state>
 (defun bar (x st state) (mv x st state))
 (bar 3 st state) ; printed 3; now prints (3 <st> <state>)
 })

 <p>The keyword @(':concrete') for @(tsee defabsstobj) and the keyword
 @(':witness-dcls') for @(tsee defun-sk) are no longer supported, as they were
 deprecated in ACL2 Version 8.4 in favor of @(':foundation') and @(tsee
 declare) forms, respectively.  Also: the following symbols, deprecated in ACL2
 Version 8.4, are no longer names of @(see events).</p>

 @({
 logical-defun
 merge-sort-symbol-<
 merge-symbol-<
 strict-merge-sort-symbol-<
 strict-merge-sort-symbol-<-cdrs
 strict-merge-symbol-<
 strict-symbol-<-sortedp
 symbol-<
 })

 <p>The string @('"Proof succeeded"') or @('"Proof skipped"') was formerly
 printed when @('SUMMARY') output is not inhibited (see @(see
 set-inhibit-output-lst)), but now that printing takes place instead when
 @('PROVE') output is not inhibited.  Thanks to Pete Manolios for pointing out
 a printing issue that is resolved with this change.</p>

 <p>Some error messages were improved for the @(see proof-builder), primarily
 when refusing a command to dive into an @('OR') expression.  Thanks to Warren
 Hunt for bringing this issue to our attention.</p>

 <p>There was a restriction on certain events, notably @(tsee defconst) and
 @(tsee defmacro) events, to ensure that they are not ancestrally dependent on
 @(tsee loop$) or @(tsee lambda$) expressions.  That restriction has been
 removed in the case that the body of the event is a quoted constant.</p>

 <p>A @(tsee defwarrant) event may complete more quickly because a generated
 hint now @(see disable)s the function.</p>

 <p>Functions that take or return @(see stobj)s may now have @(see badge)s and
 @(see warrant)s.  One cannot (yet) take advantage of these in general because
 one cannot put a @(see stobj) into a list, as required for the second argument
 of @(tsee apply$).  However, this change supports the use of stobjs in @(tsee
 loop$) expressions that use the new keyword, @('DO').</p>

 <p>The function @('the-check'), which is generated by calls of @(tsee the), is
 now a @(see guard-holder).</p>

 <p>Printing of checkpoints now takes place any time @('SUMMARY') output is
 enabled (see @(see set-inhibit-output-lst).  Formerly, both @('SUMMARY') and
 @('ERROR') output needed to be enabled.  Related tweaks, probably not
 user-visible, were made in support of utilities for obtaining and displaying
 checkpoints programmatically: see @(see checkpoint-list) (which mentions
 related utilities as well), and we thank to Eric Smith for requesting such
 utilities.</p>

 <p>The guard formula utilities (see @(see guard-formula-utilities)) continue
 to perform simplification as before, except that way to specify the level of
 simplification has changed.  Thanks to Eric Smith for a query and subsequent
 discussion that led to these changes.  See @(see guard-simplification) for a
 detailed explanation; below is a summary.  (The reason for these changes is
 that the value @('T') formerly meant different things in the two cases below
 &mdash; all simplification and limited simplification, respectively &mdash;
 and the value @('NIL') also meant different things in those two cases &mdash;
 limited simplification and no simplification, respectively.)</p>

 <ul>

 <li>For @(tsee xargs) keyword @(':guard-simplify') and related utilities
 @(tsee guard-obligation) and @(tsee verify-guards-formula):<br/>
 The default value for simplification remains @('T').  However, the value is
 now @(':LIMITED') for specifying reduced simplification; formerly it was
 @('NIL'), which is now illegal.</li>

 <li>For @(':')@(tsee guard-theorem) @(see lemma-instance)s and the related
 utility @(tsee gthm) (also the low-level utility, @('guard-theorem')):<br/>
 The default simplification is unchanged but now corresponds to a new default
 value, @(':LIMITED'); formerly it was @('T'), which is now illegal.  The value
 @('NIL') continues to be appropriate for avoiding simplification.</li>

 </ul>

 <p>Improved @(tsee untranslate) so that when untranslating a translated @(see
 term), an attempt is made to call @(tsee mv) where appropriate.  Thanks to
 Alessandro Coglio and Eric Smith for requesting this enhancement.  The
 improvement also restores type declarations under @(tsee let), @(tsee let*),
 and @(tsee mv-let) (see @(see declare) and @(see type-spec)); and it also
 restores @(tsee ignore) declarations in @(tsee let) and @(tsee let*) forms,
 where previously that was only the case for @(tsee mv-let) forms.  In
 addition, a new utility, @(tsee maybe-convert-to-mv), may be called explicitly
 to convert an untranslated term to one that calls @('mv') in leaves reached
 via transversal of the true and false branches of its top-level @('IF') tree,
 where the traversal appropriately passes through @(tsee let), @(tsee let*),
 and @(tsee mv-let) forms, as well as calls of @(tsee prog2$), @(tsee mbe),
 @(tsee mbt), @(tsee ec-call), @(tsee time$), and a few other macros related to
 @(tsee return-last) as well as @('return-last') itself.  See examples under a
 comment about ``preserving executability'' in the @(see community-book),
 @('books/system/tests/untranslate.lisp').  (Note: The changes also include a
 bug fix that avoids generating an @(tsee mv-let) expression when there are
 fewer than two bound variables.)</p>

 <p>The second argument of @(tsee certify-book) is no longer allowed to be the
 symbol, @('T'), or any symbols whose @(tsee symbol-name) is @('"T"').  (This
 option seems to have been essentially unused but it complicated the source
 code.)</p>

 <p>When an @(see event) fails while @(see useless-runes) are being read, the
 failure message now makes note of that fact.  See @(see
 useless-runes-failures).  Thanks to Mertcan Temel for pointing out that such
 failures may present a confusing problem for (especially) new users.</p>

 <p>Failed attempts to @(tsee memoize) or @(tsee profile) now generally result
 in less noisy error output.  Also, a more useful error message is printed when
 attempting to @(tsee memoize) or @(tsee profile) a function that is introduced
 either by @(tsee defabsstobj) or by @(tsee defstobj) with keyword argument
 @(':inline t'), and hence is a macro in raw Lisp; thanks to Shilpi Goel for
 suggesting this improvement.</p>

 <p>When the @(see break-rewrite) utility reports rewriting a hypothesis to
 @('nil'), it adds a note pointing to a new :doc topic, @(see tail-biting),
 that explains a way that this can happen.</p>

 <h3>New Features</h3>

 <p>A new @(tsee loop$) keyword, @('DO'), supports an imperative style of
 programming in loops.  In particular, @('DO') @('loop$') expressions may use
 @('setq') and @('mv-setq') for assigning to one or several variables
 (respectively), they may reference and return @(see stobj)s, and they may
 return multiple values.  See @(see loop$).</p>

 <p>One can now suppress output from @(tsee cw), @(tsee cw!), @(tsee
 fmt-to-comment-window), and @(tsee fmt-to-comment-window!), and from utilities
 that use these such as @(tsee time$), by inhibiting a new output type,
 @('COMMENT').  (Thus, that symbol has been added to the value of
 @('*valid-output-names*').)  See @(see set-inhibit-output-lst) and @(see
 with-output).  Thanks to Eric McCarthy for a conversation via GitHub Issue
 #1293 that led to this enhancement.  Moreover, new macros @(tsee cw+) and
 @(tsee cw!+) and new functions @(tsee fmt-to-comment-window+) and @(tsee
 fmt-to-comment-window!+) never suppress output; the @('"+"') suffix is
 intended to indicate that feature.  Thus, these new utilities behave like the
 previous utilities without the @('"+"') suffix.  Thanks to Eric Smith,
 Karthik Nukala, and Alessandro Coglio for observing inappropriate suppression
 of output from the utility @(tsee er-soft+) and the connection of this problem
 to the addition of the @('COMMENT') output type; it was resolved by using
 @('fmt-to-comment-window+') in place of @('fmt-to-comment-window') in the
 implementation of a utility underlying @('er-soft+') (see @(see
 community-book) @('books/tools/er-soft-logic.lisp')).</p>

 <p>You can now arrange that an interrupt will kill a proof immediately by
 evaluating @('(assign abort-soft nil)'), and you can restore the default
 behavior &mdash; where an interrupt instructs the proof to quit cleanly at an
 appropriate opportunity &mdash; by evaluating @('(assign abort-soft t)').
 Note that this can interfere with @(':')@(tsee redo-flat); see @(see
 abort-soft).  Thanks to Eric Smith for reporting an inability to abort a
 series of proof attempts using the @(tsee prove$) utility, which led to this
 enhancement.</p>

 <p>A @(see stobj) may now have a field of type @('STOBJ-TABLE'), which
 associates arbitrary stobj names with corresponding stobjs.  As of this
 writing, that feature should be considered experimental; see @(see
 stobj-table).  Thanks to Rob Sumners for suggesting the idea and to him and
 Sol Swords for useful design discussions.</p>

 <p>The utility @(tsee wet) has a new keyword option, @(':fullp'), that allows
 it to work even when there is a raw Lisp error.  Thanks to Eric Smith for
 requesting that @('wet') be able to work in such cases.</p>

 <p>Rewriting of @(see lambda) objects (see @(see rewrite-lambda-object)) may
 now be @(see disable)d, by disabling the @(see executable-counterpart) @(see
 rune) for (trivial function), @('rewrite-lambda-modep') &mdash; for example,
 with a hint @(':in-theory (disable (:e rewrite-lambda-modep))').  Also
 improved a couple of warnings and a bit of documentation pertaining to such
 rewriting.</p>

 <p>The undocumented @('last-ld-result') feature has been replaced by a new
 documented feature, a @(see ld-history) that records command input/output
 history.  Thanks to Eric Smith for requesting this feature.</p>

 <p>The @(tsee ld) utility accepts a new keyword argument, @(':useless-runes'),
 which functions much the same as does the @(':useless-runes') keyword argument
 of @(tsee certify-book).  See @(see useless-runes).  Thanks to Eric Smith for
 requesting this feature (which may have been requested previously as
 well).</p>

 <p>A new @(see event), @(tsee set-inhibit-er), allows the user to turn
 off error output of various types.  The related utility @(tsee
 toggle-inhibit-er) can turn on or off a single type of error output.
 Non-@(see local) versions of these utilities are @(tsee set-inhibit-er!)
 and @(tsee toggle-inhibit-er!).  Many error messages cannot yet be
 controlled this way, but this may be remedied somewhat with community
 feedback.  Thanks to Eric Smith for a request to inhibit step-limit error
 output, which led to this enhancement.</p>

 <p>The functions @(tsee l<), @('lexp'), and @('d<'), originally defined in
 @(see community-book) @('books/ordinals/lexicographic-book.lisp'), are now
 built into ACL2.  However, it is still useful to include an ordinals book, for
 example @(see community-book) @('books/ordinals/ordinals'), if you want to
 reason about such functions.</p>

 <p>A @(see stobj) field of @('HASH-TABLE') type may now specify an element
 type; for example, @('(hash-table eql nil integer)') specifies a test of
 @('eql'), no size restriction, and the element type, @('integer'), indicating
 that only integers are stored in the hash table.  The @(':initially') keyword
 of such a field is no longer ignored, but instead provides the value returned
 when looking up a key that is not bound in the hash table.  Moreover, the
 element type may be a stobj, indicating that the values in the hash table are
 all instances of that child stobj; see @(see nested-stobjs).  In that case,
 the @(':initially') keyword would be meaningless because one always gets a
 fresh instance of the child stobj when looking up an unbound key; hence
 @(':initially') is illegal for any hash-table field with a stobj element type.
 Thanks to Rob Sumners for requesting this enhancement and for helpful
 discussions about its design.</p>

 <p>It is now possible to certify a book in a logical @(see world) that
 contains @(see local) @(see events).  Thus, a book's @(see certificate) file
 may include local events among its @(see portcullis) commands, which will be
 skipped when including the book.  A key application of this new capability is
 to save an ACL2 executable (using @(tsee save-exec)) after @(see local)ly
 including set @('B') of books at the top level, and then &mdash; in fresh ACL2
 sessions started by running that executable &mdash; certify other books that
 may include some books of @('B').  Those inclusions would then be @(see
 redundant) during certification of a book, but not later when the book is
 included.  If @('B') is a large set of large books, then this process can be
 much more efficient than doing certifications from a basic ACL2 executable,
 which would involve running @(tsee include-book) on all required books from
 @('B').  Of course, one could previously have saved such an executable and
 certified books on top of it, but then all of @('B') would be included
 whenever including those books, which could be slow and also could result in
 many more rules than desired.  Thanks to Sol Swords and others at Intel
 Corp. for requesting this enhancement and engaging in initial discussions.</p>

 <p>The new macro @(tsee trust-mfc) supports testing @(see
 extended-metafunctions) outside the prover.  Thanks to Sol Swords for
 requesting such a utility.</p>

 <p>A new macro, @(tsee with-global-stobj), allows reading and writing of a
 @(see stobj) in the body of a function without having to pass it as a formal
 parameter, by accessing the stobj from the ACL2 @(see state).  See @(see
 with-global-stobj).  Thanks to Rob Sumners and Sol Swords for requesting this
 feature (originally, to support a global @(see stobj-table)) and for helpful
 discussions about its design.</p>

 <p>The @(see meta-extract) feature has been extended to allow @(see linear)
 lemmas to be extracted from the @(see world) and trusted by clause processors
 and metafunctions.  In particular, 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 representing a linear
 lemma extracted from a function symbol's @('linear-lemmas') property.  See
 @(see meta-extract), in particular the discussion of @(':linear-lemma').
 Thanks to Sol Swords for providing this enhancement.</p>

 <p>A new utility, @(tsee disable-ubt), is similar to @('(reset-prehistory t)')
 except that it does not change command numbering.</p>

 <p>Added a built-in @(':')@(tsee forward-chaining) rule,
 @('symbol-listp-forward-to-eqlable-listp'), which replaces the rule
 @('symbol-listp-forward-to-true-listp').  Note that the old rule is
 subsumed,together with other rules, by the new one.  Thanks to Warren Hunt for
 observing that not built into ACL2 as a @(':forward-chaining') rule.</p>

 <h3>Heuristic and Efficiency Improvements</h3>

 <p>Improved the efficiency of some computations involving calls of @(tsee
 defattach) with option @(':aokp t'), in particular, of @(tsee include-book)
 events for books including such calls.  Thanks to Mertcan Temel for reporting
 this efficiency issue and sending an @('include-book') event, whose execution
 time was reduced from 24 seconds to 10 seconds by this change.</p>

 <p>Evaluation of some large forms caused stack overflows (from ACL2 source
 function @('bad-lisp-consp')).  This is probably much less likely now.  Thanks
 to Eric Smith for reporting this issue to the acl2-help list with a helpful
 example, which formerly caused a stack overflow for ACL2 built on SBCL but no
 longer does so.</p>

 <p>The function @(tsee princ$) now prints characters more rapidly.</p>

 <p>In some cases, @(tsee include-book) calls may run a bit faster thanks to a
 couple of small changes.  The primary change is for heuristic @(see
 loop-stopper) generation when the conclusion of a @(see rewrite) rule contains
 a @(see lambda) expression.  Formerly all such expressions were expanded away.
 Now, they are expanded away in the left-hand side, and both the unexpanded and
 expanded versions of the left-hand side are compared to the unexpanded
 right-hand side (see the final Remark in the @(see loop-stopper)
 documentation).  We have seen a 7% reduction of time for the event,
 @('(include-book "projects/x86isa/top" :dir :system)').</p>

 <p>Book certification has (in the past, and still) an optimization that avoids
 needless rolling back of the @(see world) during the @(tsee include-book)
 phase; see @(see certify-book), in particular the discussion of ``roll back''.
 Any @(see local) event within an @(tsee encapsulate) form was reason to roll
 back the world to before that @('encapsulate') event.  That is no longer the
 case unless the @(tsee encapsulate) form introduces packages in the first pass
 through that @('encapsulate') form that are hidden or missing after the second
 pass through it, presumably because of a @(see local) @('include-book') event
 in that @('encapsulate') form.</p>

 <p>The function @(tsee len) is significantly more efficient than before.
 (Also, its raw Lisp implementation is simpler, though as before it causes an
 error for extremely (impossibly?) long lists (in Lisp parlance, whose length
 is not a fixnum).)  Thanks to Stephen Westfold for encouraging this change and
 suggesting a suitable @('declaim') form, and thanks to Eric Smith for
 providing helpful tests.</p>

 <h3>Bug Fixes</h3>

 <p>A soundness bug in @(tsee defstobj) has been fixed that allowed a field to
 contain the @(see type-spec) @('(SATISFIES pred)') when @('pred') has a @(see
 guard) other than @('t'), which generated an unsound guard theorem.  Thanks to
 Eric Smith for sending the following example.</p>

 @({
 (defstobj s (field :type (satisfies evenp) :initially 4))

 (defthm bad
   nil
   :rule-classes nil
   :hints (("Goal" :use (:instance (:guard-theorem fieldp) (x t)))))
 })

 <p>A soundness bug was due to incompleteness of the prohibition against @(see
 local) @(see portcullis) @(see command)s.  For an example, see a comment in
 the form @('(defxdoc note-8-5 ...)'), @(see community-books) file
 @('books/system/doc/acl2-doc.lisp').  This has been fixed by allowing local
 events among the portcullis commands (and treating them properly; see relevant
 discussion, including how @(tsee save-exec) may be helpful, in the ``New
 Features'' section above).</p>

 <p>The use of @(tsee set-guard-checking) before calling @(tsee certify-book)
 was making it possible for a subsequent @(tsee include-book) to fail for that
 book.  For example, in a fresh ACL2 session one could evaluate the @(see
 command) @('(set-guard-checking :none)') followed by @('(table foo 0 (car
 3))'), and then certify a book; but including that book would then fail with a
 @(see guard) violation, because the @('set-guard-checking') call was not saved
 in the @(see certificate) file, hence was not evaluated when attempting to
 include the book.  This has been fixed by treating that situation much as
 @(see local) @(see portcullis) commands are now treated (see discussion about
 that in the ``New Features'' section above).  The situation is explained now
 in the final Remark in the documentation for @(see local-incompatibility).</p>

 <p>Fixed an error that could occur when the @(see break-rewrite) utility is
 displaying failure information for an attempt to apply a @(see linear) rule
 containing @(see free-variables).  Thanks to Karthik Nukala and Eric Smith for
 sending a bug report with a replayable example.</p>

 <p>Strengthened syntax checking for accessor expressions in @(tsee stobj-let)
 bindings.  See a comment about this in @('(defxdoc note-8-5 ...)').</p>

 <p>The writing of @(see useless-runes) files was sensitive to the global @(see
 evisc-table), which could cause failures when reading those files.  This has
 been fixed.</p>

 <p>An error could occur when encountering a @(see redundant) @(tsee
 defwarrant) event while including a book.  This has been fixed, by arranging
 that a @('defwarrant') event always expands to the same @(tsee encapsulate)
 form.</p>

 <p>An assertion error was fixed, occurring with a call of @(tsee certify-book)
 when the value of environment variable @('"ACL2_USELESS_RUNES"')
 was (erroneously) @('"0"').</p>

 <p>When the @(see hints) specified for a goal include @(':do-not-induct NAME')
 for some symbol @('NAME') other than @('t'), @(':otf'),
 @(':otf-flg-override'), or @('nil'), then that goal is to be skipped, giving
 it a ``bye'' as with a @(':by') hint.  This would fail however when the @(see
 induction-depth-limit) is reached: that is, the proof would fail immediately
 rather than continuing so that the skipped goal is printed upon failure at the
 end.  The following example now has the desired behavior; thanks to Alessandro
 Coglio for raising this issue by sending a @(see proof-builder) example, where
 the @(':induct') command failed for (as it turns out) the same reason.</p>

 @({
 (set-induction-depth-limit 1)
 (thm (equal (append (append x y) z) (append x y z))
      :hints (("Goal"
               :induct t :do-not-induct foo :do-not *do-not-processes*)))
 })

 <p>Fixed a bug in processing macro arguments with more than one occurrence of
 the symbol, @(':allow-other-keys').  Thanks to Eric Smith for pointing out
 this bug and providing a fix.  Here is an example that was failing but is now
 handled without error (notice that @(':allow-other-keys') is in a value
 position, not a keyword position, so the duplication is legal).</p>

 @({
 ACL2 !>(defmacro foo (x &key y) `(list ,x ,y))

 Summary
 Form:  ( DEFMACRO FOO ...)
 Rules: NIL
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
  FOO
 ACL2 !>(foo 3 :y 4 :z 5 :allow-other-keys t :w :allow-other-keys)


 ACL2 Error in macro expansion:  ACL2 prohibits multiple :allow-other-
 keys because implementations differ significantly concerning which
 value to take.

 ACL2 !>:q

 Exiting the ACL2 read-eval-print loop.  To re-enter, execute (LP).
 ? (foo 3 :y 4 :z 5 :allow-other-keys t :w :allow-other-keys)
 (3 4)
 ?
 })

 <p>Pretty-printed output could be misaligned when an output string specified
 by the @(see evisc-table) contains a newline.  Such output is now printed a
 bit differently, with reasonable alignment.</p>

 <p>Printing of results has been improved in @(see raw-mode) in cases of @(see
 multiple-value) return, so that @(see stobj) names are used even when at least
 one returned value is not an ACL2 object.</p>

 <p>The @(see trace) level is no longer reset when entering @(see
 break-rewrite) or any other @(see wormhole).  Thanks to Khairul Azhar Kasmiran
 for raising this issue and pointing to relevant source code (<a
 href='https://github.com/acl2/acl2/issues/1395'>GitHub Issue #1395</a>).</p>

 <p>When the @(':')@(tsee pr!) command prints @(':')@(tsee rewrite) rules about
 the @(tsee pkg-imports) of one or more @(see packages), it now prints such
 rules only for relevant packages, not ones introduced earlier than specified
 by the argument of @(':pr!') (as was done previously).  Thanks to Eric Smith
 for bringing this bug to our attention.</p>

 <p>A bug in @(tsee defattach) has been fixed, which was causing the keywords
 within an argument @('(fi gi :kwdi1 vali1 ...)') to be associated with the
 wrong such argument.</p>

 <p>When printing the name of a symbol or package that consists entirely of
 '@('.')' (dot) characters, the name is escaped with vertical bars, for
 example, @('|..|').  Note that the CL HyperSpec, Section 2.3.4 Symbols as
 Tokens says: ``Any token that is not a potential number, does not contain a
 package marker, and does not consist entirely of dots will always be
 interpreted as a symbol.''  Thanks to Eric McCarthy and Eric Smith for
 pointing out that there can be errors when reading such a name when it is not
 escaped.</p>

 <p>It was possible to get a violation of fast alist discipline (see @(see
 slow-alist-warning) when certifying a book that uses @(tsee must-fail).  This
 has been fixed.</p>

 <p>It had been possible to undo commands (for example, using @(':')@(tsee ubt)
 when inside the @(see break-rewrite) interactive loop.  This destroyed the
 utility of that loop by erasing keyword aliases (see @(see
 ld-keyword-aliases)).  Thanks to Warren Hunt for reporting this problem.  The
 solution uses the new utility mentioned above, @(tsee disable-ubt), which may
 be useful for other @(tsee wormhole) invocations that take advantage of the
 @(tsee ld-keyword-aliases) @(see table).</p>

 <h3>Changes at the System Level</h3>

 <p>The @(see hons-enabled) features of ACL2 (@(tsee hons), @(see memoization),
 and @(see fast-alists)) have been included in ACL2 builds by default since
 Version 7.0 (January, 2015) and in all ACL2 builds since Version 7.2 (January,
 2016).  Now, essentially all support for building ACL2 without these features
 has been removed.  The function @('(hons-enabledp state)') and the feature
 @(':hons') both remain, but are always true and are deprecated, scheduled for
 removal very soon after the next release.  The feature @(':acl2-mv-as-values')
 was always true when feature @(':hons') was present, hence was always true; so
 it has been removed (and @('#-acl2-mv-as-values') code has been
 eliminated).</p>

 <p>For ACL2 builds when the host Lisp is SBCL, the Lisp optimization level is
 now 1 for @('SPACE'), which apparently can result in more inlining than the
 former level of 0, and which has been seen to speed up an application while
 reducing memory bytes allocated.  The default optimization level for
 @('SPACE') can be set to 1 for any Lisp at build time by running @('make')
 with argument @('ACL2_SPACE=1'), and the level can be set similarly to any
 legal value, for example by using @('ACL2_SPACE=3') for level 3.  We can
 easily change the default for other Lisps as well, and might do so when there
 is evidence that this would be useful.</p>

 <p>The function @('bind-macro-args'), and several of its subfunctions, are now
 in @(':')@(tsee logic) mode with verified @(see guard)s.  Thanks to Eric Smith
 for verifying guards as per @(see verify-guards-for-system-functions).</p>

 <p>ACL2 will now generally signal an error if a filename contains consecutive
 directory separators, i.e., @('"//"') (in non-Windows systems).</p>

 <p>(SBCL only) A build-time parameter was changed so that some non-x86 64-bit
 platforms, notably Arm, are built with @('--dynamic-space-size 32000'), as for
 x86-64 platforms, instead of @('2000').  Thanks to Stephen Westfold for
 pointing out this oversight.</p>

 <p>A new documentation topic, @(see guarantees-of-the-top-level-loop),
 explains the logical meaning of evaluation in the ACL2 read-eval-print loop,
 including discussion of attachments (see @(see defattach)), @(see badge)s,
 @(see warrant)s.</p>

 <p>The implementation of backquote has been optimized to use quoted
 expressions for constant subterms (other than @(see LAMBDA) objects) rather
 than consing new structure.  This can give a significant reduction in code
 size.  Thanks to Stephen Westfold for providing his implementation.</p>

 <p>When an error is encountered while reading an expression, the remaining
 input is cleared.  Thanks to Eric McCarthy for pointing out that this wasn't
 the case, giving the example, @('(LET ((. 3)) (+ . 4))'), as one that was
 giving many errors.</p>

 <p>(CCL only) Disabled raw lisp compiler macro for @('memq').  For example,
 the following definition no longer causes a raw Lisp error when submitted to
 ACL2: @('(defun foo (x) (member-eq x 'a))').  Thanks to Shannon Spires for the
 suggestion.</p>

 <h3>EMACS Support</h3>

 <p>It is now possible to have more than one @(see acl2-doc) buffer.  A new
 buffer is created by using @('Shift-<Return>') to follow a link.  Commands
 that are naturally specific to a given buffer (such as searching and going
 back) are buffer-local.  Thanks to Mayank Manjrekar for the idea and for
 supplying an implementation (including documentation), which has been
 incorporated into the @(see acl2-doc) source file, @('acl2-doc.el') (loaded
 from a suitable directory; see @(see emacs)).</p>

 <p>A bug has been fixed in @(see acl2-doc) that would cause an error
 when attempting to bring up the acl2-only manual.</p>

 <p>The key binding Control-TAB has been removed for the @(see acl2-doc)
 browser, to avoid conflict with other uses of that key.  Thanks to Alessandro
 Coglio for the idea.</p>

 <p>New @(tsee acl2-doc) command @('G') is similar to @('g'), prompting for a
 topic name, but puts that topic into a new buffer.  Thanks to Warren Hunt for
 requesting this feature.</p>

 <p>When @(tsee acl2-doc) fails in an attempt to download the manual, a more
 helpful error message says how to attempt the download outside Emacs, and the
 minibuffer points to an Emacs variable holding that message,
 @('acl2-doc-download-error') (which is also described in the @(see acl2-doc)
 documentation topic).  Thanks to Warren Hunt for discussion leading to this
 enhancement.</p>

 <p>Files from the @('emacs/') directory in the ACL2 distribution have been
 copied to directory @('books/emacs/').  The original @('emacs/') directory
 will continue to be maintained for Emacs 24 (though those who have used it
 comfortably with more recent versions may wish to continue to load files from
 the @('emacs/') directory).  The @('books/emacs/') directory is intended for
 use with recent versions of ACL2, and the ACL2 community is welcome to modify
 it.  Thanks to Warren Hunt for noting that users of recent Emacs versions
 could experience problems using files maintained for Emacs 24.</p>

 <h3>Experimental Versions</h3>

 <p>An error could formerly occur when using the precomputed @(see
 useless-runes) files in ACL2(r).  The @(see useless-runes) feature has now
 been turned off for ACL2(r).  Thanks to Eric McCarthy for this change.</p>

 <p>Warnings about ``fast alist discipline violated'' (see @(see
 slow-alist-warning)) could appear in ACL2(p) when @(see useless-runes) were
 being read, say using @(tsee certify-book) option @(':useless-runes :read').
 These have been eliminated.  Note that they didn't show up during regressions
 in Version 8.4 because the use of ``@('make')'' was set up to avoid using
 useless-runes with ACL2(p).</p>

 ")
other
(defxdoc note-8-6
  :parents (release-notes)
  :short "ACL2 Version  8.6 (October, 2024) 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 8.5 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-6-books) for a summary of changes made to the ACL2 Community Books
 since ACL2 8.5, including the build system.</p>

 <p><i>DARPA Note.</i>  The following statement applies to items below that are
 marked with &ldquo;See DARPA Note above&rdquo;: Release was approved by
 DARPA with &ldquo;DISTRIBUTION STATEMENT A. Approved for public
 release. Distribution is unlimited.&rdquo;</p>

 <h3>Changes to Existing Features</h3>

 <p>Some built-in functions that were formerly in @(':')@(tsee program) mode
 are now @(see guard)-verified @(':')@(tsee logic) mode functions.  Among the
 most significant such built-in functions are the following.</p>

 <ul>

 <li>@('One-way-unify') (see @('books/system/brr-near-missp.lisp'))</li>

 <li>@(tsee Genvar) (see @('books/system/brr-near-missp.lisp'))</li>

 <li>@(tsee Fmt), @(tsee error1) (which supports macros @('(er soft ...)') and
 @(tsee er-soft)), and related printing utilities &mdash; and some code was
 modified to support their conversion to @(':')@(tsee logic) mode [See DARPA
 Note above.]</li>

 </ul>

 <p>Note that because of the @(tsee error1) change noted above, @('(er soft
 ...)') can now be used in @(':logic') mode code.</p>

 <p>The connected book directory (that is, the @(see cbd)) now elaborates
 relative @(see pathname)s to absolute pathnames not only for book operations,
 but for all file operations.  For example, @('(open-input-channel
 "foo" :character state)') now interprets filename @('"foo"') relative to
 the cbd, where formerly it was generally interpreted relative to the directory
 in which ACL2 was invoked.  (Technical note: ACL2 accomplishes the new
 behavior by arranging that @(tsee set-cbd) modifies not only the cbd but also
 the Lisp global, @('*default-pathname-defaults*').)  Thanks to Alessandro
 Coglio, Eric McCarthy, and Eric Smith for suggesting consideration of such a
 change and for helpful discussions.</p>

 <p>The function @('hons-enabledp') is no longer defined, and @(':hons') has
 been removed from the Lisp global, @('*features*') (so, readtime conditionals
 @('#+hons') and @('#-hons') should be avoided, especially since @('#+hons') is
 always false even though the system is @(see hons-enabled)).  These were both
 deprecated in the preceding release (ACL2 Version 8.5).  Note that the @(see
 hons-enabled) features of ACL2 have been included in all builds by default
 since Version 7.0 (January, 2015) and in all builds since Version
 7.2 (January, 2016).</p>

 <p>The @(see proof-builder) now takes into account various aspects of
 rewriting specified by the logical @(see world) that it formerly
 ignored (pertaining to @(see match-free), @(see case-split-limitations), @(see
 untouchable) functions, non-linear arithmetic (see @(see set-non-linearp)),
 the @(see backchain-limit) for rewriting, and the @(see rw-cache-state)).</p>

 <p>The utilities @('set-inhibit-er-soft'), @('set-inhibit-er-soft!'),
 @('toggle-inhibit-er-soft'), and @('toggle-inhibit-er-soft!') have been
 renamed by dropping the suffix ``@('-soft')'', hence they are now the
 following, respectively: @('set-inhibit-er'), @('set-inhibit-er!'),
 @('toggle-inhibit-er'), and @('toggle-inhibit-er!').  The relevant table has
 similarly been renamed from @('inhibit-er-soft-table') to
 @('inhibit-er-table').  These changes reflect their relevance for the new
 utilities, @(tsee er-hard) and @(tsee er-hard), in addition to @(tsee
 er-soft).</p>

 <p>The macro @(tsee warrant) now @(tsee force)s the warrants listed.</p>

 <p>@(':')@(tsee Induction) rules now support the use of @(tsee syntaxp)
 hypotheses.</p>

 <p>The utility @(tsee read-file-into-string) has been improved in the
 following ways.</p>

 <ul>

 <li>The value of the @(':start') argument may now be any natural number less
 than the length of the input file.  (Formerly one needed to use this utility
 to read the preceding bytes first, which can be much slower.)  Thanks to Eric
 McCarthy, Eric Smith, and Grant Jurgensen for requesting this improvement and
 for helpful discussions.</li>

 <li>While the default behavior is the same for when the corresponding Lisp
 stream is closed, a new keyword argument, @(':close'), can be supplied to
 control that behavior.</li>

 <li>Miscellaneous clean-up has been made in the implementation.</li>

 <li>Restrictions have been tightened a bit to avoid what could be considered a
 soundness bug.  See discussion about that in the section on &ldquo;Bugs&rdquo;
 below.</li>

 </ul>

 <p>The @(tsee trace$) option @(':evisc-tuple :print'), which continues to use
 raw Lisp printing, has undergone the following improvements when printing
 entry and exit values.  Thanks to Eric McCarthy for a query that led to these
 improvements.</p>

 <ul>

 <li>Values are now pretty-printed.</li>

 <li>Array values are no longer displayed as @(see stobj)s.  (This includes
 stobjs themselves, since they are arrays.)</li>

 </ul>

 <p>The use of @('(:executable-counterpart rewrite-lambda-modep)') to control
 the behavior of lambda object rewriting by the prover (see @(see
 rewrite-lambda-object)) has been elaborated.</p>

 <p>Warnings for non-recursive functions in left-hand sides of rewrite rules
 (similarly for linear, forward-chaining, and type-prescription rules) now
 consider bodies of lambda objects that could be rewritten (see @(see
 rewrite-lambda-object)).</p>

 <p>The output is more informative when @(':')@(tsee pr) is applied to an
 undefined primitive, such as @('car') or @('binary-+'), or a macro-alias for
 one of those, such as @('+').  Thanks to Eric Smith for pointing out odd
 output for examples like @(':pr binary-+').</p>

 <p>The definition of @(tsee pseudo-termp) has been simplified by dropping a
 superfluous @(tsee true-listp) check.  Thanks for the suggestion from Eric
 Smith.  A new lemma, @('pseudo-termp-consp-forward'), has been added to
 prevent some existing proofs from failing due to the change.</p>

 <p>The failure message regarding @(see useless-runes) (see @(see
 useless-runes-failures)) has been restricted to the case that a proof was
 attempted by the event (though there may be rare exceptions).  Thanks to Eric
 Smith for requesting such a change.</p>

 <p>Certain guard proof obligations for @('DO') @(tsee loop$)s (so-called
 special conjectures (e), (f), and (g)) have been combined into one conjecture
 with a conjunction of three conditions in the conclusion to speed up proofs.
 See the comment starting with ``Special conjectures (e), (f), and (g)'' in the
 function @('special-conjectures') in the source file
 @('history-management.lisp').</p>

 <p>The rewriter has been changed to handle certain calls of @('ev$') faster.
 See @(see rewriting-calls-of-apply$-ev$-and-loop$-scions).</p>

 <p>A few new lemmas have been added to the standard @('apply$') book to
 simplify applications of @('assoc-equal-safe') faster.</p>

 <p>@(Csee Time-limit) and @(see theory-invariant) errors may now be inhibited
 much as @(see step-limit) errors, by using @('(set-inhibit-er
 "Time-limit")') or @('(set-inhibit-er "Theory")'), respectively.  Thanks
 to Eric Smith for requesting this enhancement and its use in the
 implementation of the utility, @(tsee prove$).</p>

 <p>A new command, @('(cmds c1 c2 ... cn)'), has been added to @(tsee
 walkabout).</p>

 <p>The documentation for @(see redundant-events) includes the following, which
 however was not enforced when the new event is in @(':')@(tsee program) mode;
 that has been fixed.</p>

 @({
   4. If either the old or new event is a mutual-recursion event, then
      redundancy requires that both are mutual-recursion events
      that define the same set of function symbols.
 })

 <p>A new feature, called ``transparent'' functions, can allow one to avoid the
 restriction on a rule of class @(':')@(tsee meta) or @(':')@(tsee
 clause-processor) that there are no common ancestors of its evaluator and meta
 function.  See @(see evaluator-restrictions) for relevant background, and see
 @(see transparent-functions) for documentation of the new feature.  Thanks to
 Mertcan Temel for requesting a way to work around that restriction, and thanks
 to Sol Swords for suggesting (and naming) the notion of transparent functions.
 We are also grateful to Sol for providing a very helpful sketch of a
 correctness proof.</p>

 <p>When there is an attachment to a common ancestor of the evaluator and meta
 function of a proposed rule of class @(':')@(tsee meta) or @(':')@(tsee
 clause-processor), the resulting error message now includes ancestor paths
 leading from the evaluator or meta function to a common ancestor.</p>

 <p>A new @(tsee walkabout) command, @('up'), moves up a level and exits the
 @('walkabout') loop when already at the top level.  It is thus equivalent to
 the existing command, @('0'), which is still supported although @('up') is
 highlighted in the documentation; see @(see walkabout)).  Thanks to Eric Smith
 for suggesting @('up').</p>

 <p>Arranged that @(see iprinting) that takes place during @(see break-rewrite)
 or @(tsee cw) is better reflected outside break-rewrite.  For examples, see
 @(see community-books) input file
 @('books/system/tests/iprint-and-brr-input.lsp'), which contains comments on
 problematic interactions between break-rewrite and iprinting in Version 8.5,
 and which generates (via the @(tsee run-script) utility) the output in file
 @('iprint-and-brr-log.txt') in that directory.  Note that @(tsee read-object)
 now updates data structures so that it can read back in what was just printed
 by @(tsee cw); see a comment in the definition of @('read-object') in the ACL2
 source code.</p>

 <p>When a defined function has a @(tsee declare) form with @('(optimize
 ...)'), that is now included in a declare form of the executable-counterpart
 function (see @(see evaluation)), which had not been the case.</p>

 <p>It had been the case that for type @(see declaration)s of @(tsee flet)
 definitions in a surrounding @(tsee defun) form, they were dropped in the
 @('defun') form's executable-counterpart (see @(see evaluation)).  Now they
 are included.</p>

 <p>The behavior of @(tsee pso) and related utilities (@(tsee pso!), @(tsee
 psof), and @(tsee psog)) has been modified to avoid introducing warnings that
 were not originally printed.  For example, the output generated by @(':pso')
 below no longer prints the warning that had been suppressed for the
 @('defthm') event below.</p>

 @({
 (set-inhibit-output-lst '(warning proof-tree))
 (defthm foo t
   :hints (("Goal" :use car-cons))
   :rule-classes nil)
 :pso
 })

 <p>The above change has additional, small output effects, probably for the
 better.  For example, output from the form @('(with-output :off (error
 summary) (thm (equal x y)))') no longer prints the line shown below (at the
 end).</p>

 @({
 ACL2 Error [Failure] in ( THM ...):  See :DOC failure.
 })

 <p>When an event fails, then if it involves definition @(see rune)s for @(tsee
 loop$) @(see scion)s, the failure message may suggest including the book
 @('projects/apply/top') if it hasn't already been included.  That book
 provides quite a few lemmas about @(tsee loop$) scions.</p>

 <p>Replaced @(tsee length) calls in the defun of @(tsee pseudo-termp) with
 calls of a new macro, @('len$'), which is a call of @(tsee mbe) that invokes
 @(tsee length) in the @(':exec') code and @(tsee len) in the @(':logic') code.
 Thanks to Eric Smith for requesting such an enhancement, and for discussing
 specifics of it, so as to avoid the need for at least one unfortunate rule
 that if @('(pseudo-termp term)') then @('(not (stringp (cdr term)))'),
 apparently needed because @('length') behaves specially on strings.</p>

 <p>When there is an error from evaluation of a form encountered by @(tsee ld),
 in a session where the value of @(tsee ld-error-triples) is the default of
 @('t') and the value of @(tsee ld-error-action) is of the form @('(:EXIT N)'),
 then ACL2 quits with exit status @('N') in some cases where formerly it did
 not.  The following explanation is rather technical; see @(see
 ld-error-action) for relevant background.</p>

 <blockquote>

 <p>This behavior was already present in the case that the &ldquo;error on
 evaluation&rdquo; was from an evaluation result @('(mv erp val state)') where
 @('erp') is non-@('nil'); but it has been extended to the case that @('erp')
 is @('nil') and @('val') is of the form @('(:STOP-LD . x)'), as is returned by
 default by @('ld') upon an evaluation error.  A key effect of this change is
 for the case that a @('.acl2') file produces an error from a call of @(tsee
 build::cert.pl).  The following example illustrates; explanation follows
 below.</p>

 @({
 ;;; foo.acl2
 (ld '((defun g (x) y)) :ld-error-action :return!)

 ;;; foo.lisp
 (in-package "ACL2")
 })

 <p>Before this change, the command &lsquo;@('cert.pl foo')&rsquo; resulted in
 a hard Lisp error (as seen in @('foo.cert.out')).  To see why, first note that
 @('cert.pl') executes a sequence of commands as follows (several omitted as
 shown with &ldquo;@('...')&rdquo;).</p>

 @({
 ...
 (set-ld-error-action (quote (:exit 1)) state)
 ...
 ; instructions from .acl2 file foo.acl2:
 (ld '((defun g (x) y)) :ld-error-action :return!)
 ...
 #!ACL2 (set-ld-error-action (quote :continue) state)
 ...
 })

 <p>The call of @('ld') above returns @('(mv nil (:STOP-LD 2) state)').
 Because @('ld-error-action') at the top level no longer has the default value
 of @(':CONTINUE'), that result is considered an error (see @(see
 ld-error-action)) and top-level evaluation halts.  Before this change, then
 ACL2 did not quit since the value was of the form @('(mv nil _ state)');
 instead, ACL2 would quit the top-level call of @('ld'), leaving us in raw
 Lisp.  But in raw Lisp, the @('#!') reader macro (see @(see
 sharp-bang-reader)) is undefined; hence an error would be signaled.  After
 the fix, the return value of @('(mv nil (:STOP-LD 2) state)') is treated as an
 error, so because @('ld-error-action') is @('(:EXIT N)'), ACL2 immediately
 exits with status @('N').</p>

 </blockquote>

 <p>The pretty-printer has been improved by a contribution from Stephen
 Westfold to support appropriate indentation, including more conventional
 pretty-printing for calls of common macros such as @(tsee defun) and @(tsee
 defmacro).  See @(see ppr-special-syms); we thank Stephen also for supplying
 the substance of that documentation.  Thanks too to Stephen for suggesting
 several user-defined macros to be pretty-printed with this mechanism, which we
 have modified by adding suitable @(tsee table) events (e.g., for @(tsee
 define)).</p>

 <p>Runtime @(see guard) violation messages from @('DO') @(tsee loop$)
 expressions are now much more readable.  They also now include a pointer to
 the @(see do-loop$) documentation, which has new, relevant explanation (first
 in brief, later in detail) regarding such messages.</p>

 <p>Four obsolete fields of the ACL2 @(see state) have been removed:
 @('big-clock-entry'), @('t-stack'), @('32-bit-integer-stack'), and
 @('list-all-package-names-lst'), as have some related built-in, undocumented
 definitions and theorems, including @('old-check-sum-obj') and supporting
 functions.</p>

 <p>Improved @(tsee hide) calls in prover output from failed execution of @(see
 warrant)s, by adding suitable notes about attachments or warrant functions not
 being executable during proofs.  Thanks to Eric McCarthy for a remark that led
 to this change.</p>

 <p>State globals @('inhibit-output-lst'), @('inhibited-summary-types'), and
 @('ld-level') are now @(see untouchable).  The macros @(tsee
 set-inhibit-output-lst) and @(tsee set-inhibited-summary-types) still allow
 you to modify the values of these variables.  Thanks to Peter Dillinger for
 correspondence (years ago!) leading to these changes.</p>

 <p>The macro @(tsee state-global-let*) no longer requires explicitly supplying
 a setter for certain built-in @(see state) global variables.  See @(tsee
 state-global-let*).</p>

 <p>A proposed @(tsee defaxiom) @(see event) is no longer @(see redundant) with
 an existing @(tsee defthm) event.  Before this change, the following book
 could (perhaps unfortunately) be certified, even without @(tsee certify-book)
 option @(':skip-proofs-okp t').</p>

 @({
 (in-package "ACL2")
 (local (defthm foo (equal (car (cons x x)) x)))
 (defaxiom foo (equal (car (cons x x)) x))
 })

 <p>The prover sometimes reduces a goal without hypotheses (technically
 speaking, a one-element @(see clause)) to @('nil') using <see topic='@(url
 type-reasoning)'>type reasoning</see>.  This heuristic has not changed, but
 formerly there was no explanation given.  Now ACL2 reports the rules (of class
 @(':')@(tsee type-prescription)) that were used.</p>

 <p>The default for @(tsee memoize) keyword argument @(':verbose') has been
 changed from @('t') to @('nil'), which (by default) eliminates noise from the
 output.</p>

 <p>When a proof attempt is halted so that it reverts to prove the original
 goal by induction, the top-level checkpoints are printed under the @(see
 summary) under the banner, &ldquo;@('Key checkpoints before reverting to proof
 by induction')&rdquo;.  This was normally the case already, but not in the
 special case that the proof is eventually aborted either because a goal of
 @('NIL') is produced or because proof by induction is not allowed (due to a
 @(':DO-NOT-INDUCT') hint or an @(see induction-depth-limit) being exceeded).
 Thanks to Eric Smith for a chat that helped lead to this improvement.</p>

 <p>For most built-in @(see table)s, error messages for guard failures have
 been improved, by use of a new macro that is also available to ACL2 users:
 @(tsee set-table-guard).  That utility may be used to set a @(see table) guard
 in a way that produces a user-friendly error message when the guard fails.</p>

 <p>The prover may now print a parenthetical remark about &ldquo;dropping false
 conclusion&rdquo;.  That remark points to a new documentation topic, which
 provides explanation: see @(see clause).</p>

 <p>@(csee State) global @('trace-co') is now untouchable.</p>

 <p>ACL2 now warns when the hypothesis of a @(see type-prescription) or @(see
 forward-chaining) rule is a call of @(tsee syntaxp) or @(tsee bind-free),
 since these get no special treatment for such rules.</p>

 <p>The utility @(tsee get-event-data) now returns data from the proof done on
 behalf of a @(tsee thm) event, rather than from the surrounding @(tsee
 make-event) call used for implementing @('thm').  Thanks to Eric Smith for
 requesting this change.</p>

 <p>In the case that a proof is interrupted after @('(set-debugger-enable t)')
 and then aborted, ACL2 formerly printed failures in a special way, in
 particular showing the @(see pstack).  This is no longer the case: all @(see
 event) failures are printed in the same way.</p>

 <p>A new key, @('EVENT'), is available for @(tsee get-event-data).  Thanks to
 Eric Smith for a discussion leading to this addition.</p>

 <p>Most ACL2 reader errors are now ACL2 hard errors rather than raw Lisp
 errors (as they were formerly).  As a result, such errors can sometimes be
 &ldquo;caught&rdquo; by suitable programming.  Thanks to Grant Jurgensen and
 Eric Smith for requesting this change.  Note that input is still flushed in
 these cases, perhaps more thoroughly than before.</p>

 <p>@(tsee Break-rewrite), @(tsee brr-commands), @(tsee monitor), and @(tsee
 unmonitor) have been radically changed but in a largely backwards compatible
 way.  It is now possible to cause interactive breaks when a monitored rule is
 tried but fails to match the target.  See @(tsee monitor), in particular, see
 the &ldquo;near-miss&rdquo; break criteria in @(tsee monitor) for a
 discussion.  Changes to @(tsee break-rewrite) largely just correct anomalous
 behavior.  One significant behavioral change is that the list of monitored
 runes is locally bound by @('break-rewrite'), so that while it can be changed
 in inferior breaks, when control returns to superior levels (and to the
 top-level) the list of monitored runes is unchanged.  Related changes are
 discussed in the following three items.  [See DARPA Note above for this work,
 including the following three items.]</p>

 <ul>

 <li>The @(tsee brr)-command @(':')@(tsee p!) (see @(see brr-commands)) has
 been redefined so that in @(see break-rewrite) it is a no-op.  (Actually, it
 did not always work as advertised in @(see break-rewrite)!  Its behavior
 outside of break-rewrite is unchanged.)  A comment in the source code
 definition of @('p!') explains why.</li>

 <li>The function @('get-wormhole-status') is deprecated, and its new name is
 @(tsee get-persistent-whs).</li>

 <li>The macro @('show-brr-evisc-tuple') has been eliminated, but @(tsee
 brr-evisc-tuple) is available instead.</li>

 </ul>

 <p>The definition of @('bounded-integer-alistp') has been modified by adding a
 guard @('(posp n)') and removing the @('(integerp n)') test from the body of
 its @(tsee defun).  [See DARPA Note above.]</p>

 <p>As before, when calling @(tsee break$) from a @(see wormhole) &mdash; for
 example when inside @(see break-rewrite) &mdash; one is left at a raw Lisp
 prompt.  However, when returning from that prompt (e.g., with @(':q') if the
 host Lisp is CCL), one no longer stays in the wormhole, as noted by a message,
 &ldquo;Aborting to top level from a wormhole break (see :DOC
 wormhole).&rdquo;  [See DARPA Note above.]</p>

 <p>The function @('iprint-oracle-updates'), which is called by @(tsee
 read-object), is now @(see disable)d, because it was made more complicated
 to accommodate the conversion of function @('eviscerate-top') into
 @(':')@(tsee logic) mode.  [See DARPA Note above.]</p>

 <p>The utilities @(':')@(tsee pe) and @(':')@(tsee pr) now provide more useful
 output when applied to function symbols that are built into ACL2 without a
 defining event.  Thanks to Warren Hunt for discussions leading to this
 improvement.</p>

 <p>The @(tsee guard)s and bodies have changed slightly for some built-in
 function definitions, as follows.</p>

 <ul>

 <li>For functions @(tsee princ$), @('prin1$'), @(tsee explode-atom), and
 @('explode-atom+'), the guard now requires of the first argument only that it
 be an atom; it no longer must be a &ldquo;good atom&rdquo;, i.e., a number, a
 character, a string, or a symbolp.  As a result, the definition bodies of
 @(tsee princ$), @('prin1$'), and @(tsee explode-atom) have been tweaked
 slightly.</li>

 <li>The guards for @('packn1'), @(tsee packn-pos),
 @('find-first-non-cl-symbol'), and @(tsee packn) have similarly been weakened
 to require only @(tsee atom-listp) instead of @('good-atom-listp'), and the
 definition of @('good-atom-listp') has been removed.</li>

 <li>The guard for @('(prin1$ x channel state)') now requires @('(symbolp
 channel)'); it was a bug that this conjunct was formerly omitted.</li>

 <li>Several functions that take @(tsee state) had guards requiring that
 built-in @(see state) globals &mdash; those bound in @('initial-global-table')
 &mdash; are bound in the global-table of the @(see state) (using
 @('f-boundp-global') or @('boundp-global')).  However, the predicate
 @('state-p1'), which recognizes ACL2 @(see state)s, implies that these
 conditions all hold; so, they have been removed from those guards.  Such a
 test has also been removed from the definition of @('main-timer').</li>

 </ul>

 <p>The utility, @(tsee break-on-error), now causes a much cleaner error when
 invoked in @(see raw-mode).  The installation of breaks by @('break-on-error')
 works even in raw-mode &mdash; it's just that evaluation of a call of
 @('break-on-error') must not take place in raw-mode.  Also, the effect of
 @('break-on-error'), to cause breaks on errors, works better after entering
 raw-mode than it did previously, when evaluation of a form @('(er hard ....)')
 would fail to enter the debugger: that has been fixed.  Evaluation of @('(er
 soft ....)')  continues to invoke such breaks whether or not in raw-mode.  A
 new aspect of @('break-on-error') is that breaks occur not only for hard and
 soft errors, but also when aborting to the top level (which is what happens
 when @('(er hard ...)') is called in raw-mode).  Thanks to Eric McCarthy for
 reporting issues that led to these improvements.</p>

 <p>When @(tsee ld) is invoked with a non-@('nil') value of keyword
 @(':ld-missing-input-ok') and the input file is missing, the value returned is
 now @(':missing-input') instead of @(':eof').</p>

 <p>When @(tsee defbadge) is applied to a function symbol that is built into
 ACL2 with a @(see badge), such as @(tsee nth), the result is a no-op and an
 @(see observation) is printed to that effect.  (Formerly the @('badge-table')
 was needlessly extended and ACL2 reported that the function symbol was being
 given a badge.)</p>

 <p>Suppose that a @(tsee verify-guards) event for a defined function symbol,
 @('fn'), does not include a @(':hints') keyword, but the existing definition
 of @('fn') includes a @(':guard-hints') keyword in its @(tsee xargs) @(see
 declaration).  Then, unlike previously, the value of that @(':guard-hints')
 keyword is now used as the value of @(':hints') for that @('verify-guards')
 event.  The keywords @(':guard-debug') and @(':guard-simplify') of
 @('verify-guards') similarly now default to values of the corresponding
 @('xargs') in the old definition, if supplied there.  This change brings the
 behavior of @('verify-guards') in line with that of @(tsee
 verify-termination).  See @(see verify-guards) for a discussion of the case of
 @(tsee mutual-recursion), where only the definition of @('fn') is relevant for
 keyword values, not other definitions in its clique.</p>

 <p>A hint of the form @(':induct X') is now an error if @('X') is an atom
 other than @('t') or a quoted constant, since those do not suggest any
 induction scheme.  Thanks to Eric Smith for raising the question of what
 @(':induct nil') should do and helping with examples showing that the current
 behavior is not really consistent.  Thanks to Alessandro Coglio for suggesting
 that @(':induct nil') cause an error since it serves no purpose and could be
 confused with @(':do-not-induct t'), which is quite different.</p>

 <p>The built-in @(tsee defaxiom) events @('code-char-char-code-is-identity')
 and @('char-code-code-char-is-identity') no longer have @(tsee force)d
 hypotheses.  Thanks to Alessandro Coglio for pointing out that these @(see
 rewrite) rules were rather unique as built-in rewrite rules that force
 hypotheses.  Note that the original versions of these two rules, stated as
 @(tsee defthm) events with suffix @('"-FORCED"') added to the names, may be
 found in community book
 @('books/std/basic/code-char-char-code-with-force.lisp'); including this books
 (perhaps @(see local)ly) may rescue a proof that now fails because of the
 change.</p>

 <p>Fixed an induction message when limiting the number of cases, in
 particular, replacing &ldquo;we had to fold ... into a single
 IF-expression&rdquo; by &ldquo;we had to termify ... (see :DOC termify)&rdquo;
 and explaining in the new @(see documentation) topic, @(see termify).</p>

 <p>It is now legal to introduce more than one @(see elim) rule for the same
 function symbol.  Thanks to Eric Smith for pointing out that the current
 implementation was inconsistent in accepting a replacement @(see elim) rule
 when including a book but not at the top level.</p>

 <p>It is no longer illegal to read a @(see stobj) when in a @(see wormhole)
 state, for example, when inside @(see break-rewrite).</p>

 <p>In @(see gag-mode) (which is on by default), when the prover notes that a
 forcing round is pending, it now lists the names of the rules that are
 responsible.</p>

 <p>A hash-table or stobj-table field of a @(see stobj) may now specify a size
 that is a constant symbol with a suitable value.  See @(see defstobj) and see
 @(see stobj-table).  The meaning is the same as if the size had been given as
 the value of that constant.  Thanks to Warren Hunt for requesting this
 enhancement.</p>

 <p>The fifth formal of @(tsee do$) now represents the values returned rather
 than a default value.  This change supports a bug fix; see the item below
 regarding &ldquo;About a bug in DO$ in ACL2 Version  8.5&rdquo;.</p>

 <p>The sixth and seventh arguments of @(tsee do$) have been combined into a
 record that also contains a list of the names of all the @(tsee stobj)s in the
 @('DO') @('loop$').  In the new record, the measure term is stored in
 untranslated form.  The record is only used in the hard error produced when
 the evaluation of a @('DO$') term fails to terminate and is not relevant to
 the logical value of the @('DO$') term.</p>

 <p>It is now legal for the parent stobj of a @(tsee stobj-let) expression to
 occur free in the producer when no producer variable is bound in the bindings.
 For an example, see the section &ldquo;Allow the parent stobj of a stobj-let
 expression to occur free in the producer when no variable bound in the
 bindings occurs in the producer.&rdquo; in @(see community-book)
 @('books/system/tests/nested-stobj-tests.lisp').</p>

 <p>Built-in function @('bounded-integer-alistp2') has been modified to remove
 @(tsee integerp) tests on formals @('i') and @('j') from the body and instead
 require them to satisfy @(tsee posp) in the @(see guard).</p>

 <p>ACL2 versions of Lisp &lsquo;fixnum&rsquo; notions have been made more
 generous.  Specifically, the value of @('*fixnum-bits*') has been increased
 from 30 to 61, which has increased the value of @('(fixnum-bound)') from
 2^29-1 to 2^60-1.  Thanks to Eric Smith for requesting an increase.  One
 effect of this change is to increase the value of @('*default-step-limit*')
 accordingly, so that the steps computed by @(see with-prover-step-limit) will
 no longer be limited to fewer than 2^29.

 <blockquote>

 <b>NOTE</b>.  The previous such &ldquo;fixnum&rdquo; behavior can be obtained
 by building ACL2 with environment variable @('ACL2_SMALL_FIXNUMS') set to a
 non-empty value.  In fact, such a setting is necessary for a 32-bit Lisp such
 as CMUCL.  However, such ACL2 builds are not as fully tested as the usual
 builds and thus may be less reliable, and they are not guaranteed to work
 compatibly with ordinary ACL2 builds on the same set of books.

 </blockquote></p>

 <p>Changed the bound @('*maximum-positive-32-bit-integer*') that was used for
 array lengths (and eliminated that constant), replacing it by the larger value
 from macro call @('(array-maximum-length-bound)'), which is the same as
 @('(fixnum-bound)'), i.e., @(`(fixnum-bound)`).  Thanks to Eric Smith for
 suggesting that we consider such a change and for updating books under
 @('books/kestrel/').  Note: For CMUCL (or any 32-bit Lisp) the bound has
 actually decreased, since @('(fixnum-bound)') is @('2^30-1') in that case.</p>

 <p>The @(tsee case-match) macro now generates an @('ignorable') @(tsee
 declare) form in a clause, for any variable occurring more than once in the
 pattern.  This can free the user from the need to do so.  The following
 example illustrates this change: it now evaluates without error, but before
 this change one needed to add @('(declare (ignorable x))') or
 @('(declare (ignore x))') as shown.</p>

 @({
 (let ((e '(a a))) ; same problem for '(a b) instead of '(a a)
   (case-match e
     ((x x)
      ;; Formerly needed (declare (ignorable x)) or (declare (ignore x)) here.
      t)
     (& nil)))
 })

 <p>The @(see guard)s for functions that operate on characters or strings
 sometimes insisted that the inputs contain only standard characters.  That
 restriction has been lifted, and the definitions of @(tsee alpha-char-p),
 @(tsee upper-case-p), @(tsee lower-case-p), @(tsee char-downcase), and @(tsee
 char-upcase) have been adjusted to handle non-standard characters.</p>

 <p>The predicate @('state-p'), which recognizes ACL2 @(see state) objects, now
 requires that @(tsee print-base-p) hold of state global @('print-base').
 Also, function @('print-base-p') is now @(see disable)d by default.</p>

 <p>The predicate @('standard-string-alistp') has been deleted, while a related
 predicate @(tsee string-alistp) has been added.</p>

 <p>The @(see break-rewrite) facility will now cause an interactive break on a
 monitored rewrite rule if the rule's equivalence relation fails to refine any
 of the equivalence relations known to be permitted while rewriting the target.
 See @(see geneqv) for a discussion of how @(see congruence) rules are used to
 compute permitted equivalence relations and @(see refinement-failure) for
 advice about how to investigate and fix refinement failures during
 rewriting.</p>

 <p>The message for evaluation failures during proofs has been modified
 slightly, clarifying the case of substitution and, especially, suggesting
 :DOC @(see comment) for explanations (which has been updated accordingly).
 Thanks to David Russinoff for an acl2-help list query leading to this
 improvement.</p>

 <p>It is no longer illegal for a @(tsee defstobj) event both to specify
 keyword argument @(':NON-EXECUTABLE T') and to use the @(':CONGRUENT-TO')
 keyword argument.</p>

 <p>@('Lambda') objects in positions of @(see ilk) @(':FN') are now subjected
 to a size limitation.  See @(tsee explain-giant-lambda-object).</p>

 <h3>New Features</h3>

 <p>ACL2 now supports floating-point operations.  See @(see df).  Regarding
 this new feature: Release was approved by DARPA with &ldquo;DISTRIBUTION
 STATEMENT A. Approved for public release. Distribution is unlimited.&rdquo;
 Note for system programmers: the new <i>df expressions</i> affect translation
 as well as stobjs-in and stobjs-out; see @(see system-utilities), specifically
 discussion mentioning &ldquo;df&rdquo;.  Thanks to Warren Hunt for his
 encouragement and support in this effort, towards ACL2 usage in scientific
 computations.</p>

 <p>The new zero-ary attachable system function, @(tsee heavy-linear-p), allows
 for enhanced use of @(see linear-arithmetic) during rewriting, specifically
 with the test (first) argument of a call of @('IF').  Thanks to Eric Smith for
 suggesting the development of such a feature, which can be useful in
 rewriting-based tools.</p>

 <p>There is a new `@('make')' target to build an ACL2 executable using
 @('save-exec').  See @(see save-exec), in particular the new discussion at the
 end of that topic.  Thanks to Eric Smith for requesting such a utility.</p>

 <p>New utilities @(tsee get-cpu-time) and @(tsee get-real-time) return the cpu
 time and real (wall clock) time that has elapsed since the start of the ACL2
 session.  Thanks to Eric McCarthy for suggesting the addition of such
 utilities.</p>

 <p>The new utility @(tsee er-hard) is analogous to @(tsee er-soft), but for
 hard errors instead of soft errors (see @(see er)).</p>

 <p>A new command, @(':')@(tsee tc) (translate and clean), has been added.  It
 translates a given form and then ``cleans it up'', returning a logically
 equivalent but often simpler term in which logically irrelevant but
 operationally important tags have been removed.  The variants @(':')@(tsee
 tca) and @(':')@(tsee tcp) use different degrees of ``cleaning.''  These are
 particularly useful for seeing the logical meanings of @(tsee loop$) terms as
 well as terms involving @(tsee mbe) and @(tsee return-last).</p>

 <p>A directory of @(see books) may now be relocated so that those books are
 still treated as certified.  This is supported by a new @(tsee
 project-dir-alist), which associates keywords with ``project directories'' and
 is set using environment variable @('ACL2_PROJECTS'); see @(see
 project-dir-alist).  By default, the @('project-dir-alist') has only one
 entry, which associates the keyword @(':SYSTEM') with the @(see
 community-books) directory, @('books/').  The @('project-dir-alist')
 generalizes the notion of system books directory, assigning meaning to the
 @(':dir') argument of @(tsee include-book) and @(tsee ld) and to @(see
 sysfile) arguments of @(tsee add-include-book-dir) and @(tsee
 add-include-book-dir!).  Thanks to Sol Swords for requesting such a capability
 and for helpful design discussions.  (Technical Note: Implementation-level
 changes are summarized in comments in the form @('(defxdoc note-8-6 ...')) in
 @(see community-book) @('system/doc/acl2-doc.lisp').)</p>

 <p>A new @(see break-rewrite) command, @(':pot-list'), shows the list of the
 polynomials that are assumed in the current context.  See @(see brr-commands)
 and see @(see brr@).  Thanks to Alessandro Coglio and Eric Smith for
 conversations leading to this enhancement.</p>

 <p>It is now possible to cause @(tsee make-event) to do proofs during its
 expansion phase even in a context where proofs are generally skipped (see
 @(see ld-skip-proofsp)).  See @(see make-event), in particular the discussion
 there labeled as &ldquo;(4)&rdquo;.  Thanks to Eric Smith for requesting such
 a feature.</p>

 <p>The induction mechanism in the prover can now deduce induction suggestions
 from some @('DO') @('loop$')s.  See @(see
 stating-and-proving-lemmas-about-loop$s) for a brief discussion.</p>

 <p>A new @(':')@(tsee linear) rule, @('acl2-count-car-cdr-linear'), is now
 built into ACL2, as follows.  Thanks to Eric Smith for suggesting this
 improvement (slightly renamed here) to what we originally added.</p>

 @(def acl2-count-car-cdr-linear)

 <p>The Common Lisp utility, @(tsee macrolet), is now supported in ACL2.
 Thanks to Alessandro Coglio for discussion leading us to make this addition.
 See @(see macrolet).</p>

 <p>The utilities @(tsee with-output) and @(tsee with-output!) have been
 enhanced in the following two ways; see @(see with-output) for details.</p>

 <ul>

 <li>A new keyword, @(':inhibit-er-hard'), can be supplied a non-@('nil') value
 to turn off hard errors when error output is inhibited.  Thanks to Eric Smith
 for a conversation leading to this enhancement.</li>

 <li>The keyword @(':off') for the utility @(tsee with-output) (also @(tsee
 with-output!)) can take on a new value, @(':all!'), which is treated exactly
 the same as using arguments @(':off :all :gag-mode nil :inhibit-er-hard
 t').</li>

 </ul>

 <p>The new utility @(tsee with-cbd) creates a scope for an indicated value of
 the connected book directory (see @(see cbd)).  Calls of @('with-cbd') are
 allowed in @(see books) as well as in @(tsee encapsulate) and @(tsee progn)
 @(see events); see @(see embedded-event-form).  Thanks to Sol Swords for
 requesting that @('with-cbd') be legal in embedded events.  Thanks to Sol
 Swords and Mertcan Temel for reporting a bug in an initial implementation.</p>

 <p>The new utility, @(tsee with-current-package), evaluates a given form with
 respect to an indicated @(see current-package).  Thanks to Sol Swords for
 requesting this utility.</p>

 <p>See @(see fast-cert) for a &ldquo;fast-cert&rdquo; mode for faster, but
 possibly unsound, book certification, in particular when using a saved
 executable that contains @(see local) events.  Thanks to Sol Swords for
 requesting such a capability and for helpful design discussions.</p>

 <p>Added utility @(tsee set-warnings-as-errors), which can change @(see
 warnings) to hard @(see errors).  Thanks to Mark Greenstreet for the idea and
 for discussions that were helpful in refining it.</p>

 <p>A new @(tsee LD) special, @(tsee ld-always-skip-top-level-locals), has the
 effect of skipping @(tsee local) top-level forms.  Thanks to Sol Swords for
 requesting such a capability, to support faster loading of @('.port') files by
 the build system (see @(tsee build::cert.pl)).</p>

 <p>The symbol, @('number'), is now a legal @(see type-spec).</p>

 <p>It is now permitted for a @(see stobj) @('s') to occur more than once as an
 actual parameter in a function call, provided each such occurrence is in a
 position where a stobj congruent to @('s') is expected (possibly @('s')
 itself).  Thanks to Sol Swords for providing a relevant example, which appears
 in a comment in the definition of function @('stobjs-in-out') in the ACL2
 sources.</p>

 <p>A new utility, @(see with-brr-data), together with related query utilities,
 allows one to find the source of a term in prover output.  Thanks to Sol
 Swords for requesting something like this in 2008 (!) and to Eric Smith for
 requesting a related utility (see @(see community-books)
 @('kestrel/utilities/brr-data-failures.lisp') and
 @('kestrel/utilities/brr-data-all.lisp')).  See @(see with-brr-data).</p>

 <p>@(tsee Make-event) takes a new keyword, @('save-event-data').  When that
 keyword is non-@('nil'), event-data from the expansion saved is preserved; see
 the new section at the end of @(see make-event-details).  This new feature was
 motivated by the desire to preserve a proof's event-data in calls of @(tsee
 thm), as described in the &ldquo;Changes&rdquo; section above.</p>

 <p>New utilities allow one to explore what has changed when an event fails in
 a book that formerly certified.  See @(see saving-event-data).  Thanks to Eric
 Smith for requesting such a capability and for helpful bug reports for early
 versions of these utilities.</p>

 <p>A new legal value for @(tsee set-verify-guards-eagerness), @('3'), causes
 guard verification even when @(':verify-guards nil') has been @(see declare)d.
 This can be helpful when a @(tsee verify-termination) event in a book is
 intended to verify @(see guard)s but a @(see local)ly included book declares
 @(':verify-guards nil') in the corresponding @('verify-termination')
 event.  (Technical note: That issue occurs because @('verify-termination')
 invokes @(tsee make-event), and the expansion is saved when locally including
 the sub-book.)</p>

 <p>When environment variable @('ACL2_WRITE_BOOKDATA') has a non-empty value,
 then files of the form @('*__bookdata.out') will be written; see @(see
 bookdata) for explanation and an exception.  Thanks to Eric Smith for
 requesting this enhancement.</p>

 <p>@(tsee Thm) now takes an optional @(':instructions') keyword argument, like
 @(tsee defthm).  Thanks to Warren Hunt for requesting this enhancement.</p>

 <p>New utilities @(tsee trans*) and @(tsee trans*-) can show repeated
 macroexpansions of a form leading to its final translation, where @('trans*')
 also shows @(tsee make-event) expansions.  Thanks to Warren Hunt for
 requesting a utility that does repeated macroexpansion.</p>

 <p>A new command has been added to the @(see proof-builder-commands), to
 display the linear arithmetic database.  See @(see acl2-pc::pot-lst).  Thanks
 to Dave Greve for bringing forward the idea of such a command.</p>

 <p>The utility @(tsee set-raw-proof-format) now takes a new legal value,
 @(':clause'), which is like @('t') except that in addition to printing @(see
 rune)s as lists in output from the simplifier, it prints all goals as @(see
 clause)s.  Thanks to Eric Smith for encouraging such an enhancement.</p>

 <p>It is possible to cause ACL2 to increase its effort in @(see
 type-reasoning).  See @(see set-dwp).  Thanks to Eric Smith for correspondence
 leading to this feature.</p>

 <p>The new documentation topic, @(see induction-coarse-v-fine-grained),
 discusses how appropriately setting ruler-extenders can sometimes improve the
 induction scheme suggested by a recursive function, especially one involving
 @(tsee let) and @(tsee let*) bindings containing conditional recursive calls.
 For that new topic, new related books @('books/demos/ppr1-experiments.lisp')
 and @('books/demos/ppr1-experiments-thm-1-ppr1.lisp'), and related edits of
 existing :DOC topics (@(see advanced-features), @(see definductor), @(see
 defun), @(see induction), @(see rulers), @(see verify-termination), and @(see
 xargs)): Release was approved by DARPA with &ldquo;DISTRIBUTION STATEMENT
 A. Approved for public release. Distribution is unlimited.&rdquo;</p>

 <p>A new supported value for @('(@ script-mode)'), @('skip-ldd-n'), directs
 the @(tsee run-script) tool to prevent @(see history) commands such as
 @(':')@(tsee pe) from printing event numbers.  That can make the output less
 sensitive to ACL2 changes.  For an example, see the use of @('(assign
 script-mode 'skip-ldd-n)') in @(see community-book) file
 @('books/demos/floating-point-input.lsp').</p>

 <p>A new @(see stobj) field keyword, @(':element-type'), is legal for an array
 field.  It specifies the raw Lisp element type of the array.  Its value can be
 the element type specified by the value of the @(':type') for that array
 field.  That is the default value, and the other legal value is @('t'), but
 these may change in the future.  See @(see defstobj) and see @(see
 defstobj-element-type).</p>

 <p>A new @('brr') command, @(':')@(tsee explain-near-miss), when issued in a
 break caused by a near miss, will try to pinpoint how the rule's pattern
 failed to match the current target.</p>

 <p>A new utility, @(tsee compare-objects), highlights the differences between
 two @('cons')-trees.</p>

 <p>Now @(tsee defabsstobj) accepts the @(':non-executable') keyword, in
 analogy to support for that keyword by defstobj.  Thanks to Yahya Sohail and
 Warren Hunt for discussions leading to this enhancement.</p>

 <p>New functions @(tsee add-global-stobj) and @(tsee remove-global-stobj)
 change whether there is a global (&ldquo;live&rdquo;) stobj for a given stobj
 name, thus modifying the effect of the keyword @(':non-executable') of events
 @(tsee defstobj) and @(tsee defabsstobj).  Thanks to Yahya Sohail and Warren
 Hunt for discussions leading to the addition of these utilities.</p>

 <p>A new @(tsee defabsstobj) keyword, @(':attachable'), allows a single
 abstract @(see stobj) to have more than one foundation and associated
 functions for execution, without the need to recertify the book that
 introduces the stobj.  See @(tsee attach-stobj).  Thanks to Warren Hunt and
 Yahya Sohail for requesting this feature.  We thank Sol Swords, Warren, and
 especially Yahya for helpful input on its high-level design.</p>

 <h3>Heuristic and Efficiency Improvements</h3>

 <p>Added a &ldquo;desperation heuristic&rdquo; to compute a stronger context,
 for the extra try at simplification made after a goal is not changed by
 simplification.  Thanks to Warren Hunt and Vivek Ramanathan for supplying an
 example of a theorem whose proof had a surprising failure but now
 succeeds.  (Technical Remark describing this change: When a @(see clause) has
 most recently settled down at the time that the simplify process is invoked (a
 so-called &ldquo;desperation heuristics&rdquo; attempt), then the literals are
 reordered before building the @(see type-alist), so that the literals that
 involve at most one variable precede the other literals.)</p>

 <p>Generation of guard @(see clause)s (and, probably rarely, other goals) has
 been sped up in certain extreme cases.  For details, see @(see
 system-attachments), specifically the discussion of CONJOIN-CLAUSE-SETS-BOUND
 in the &ldquo;Summary of attachable system functions&rdquo;.  Thanks to
 Alessandro Coglio for sending an example that led to our discovery of the
 quadratic behavior eliminated by this change.</p>

 <p>Duplicate entries in @(see type-alist)s (proof contexts) are now avoided in
 many cases.  (Implementation note: some calls extending the type-alist with an
 existing term/type-set pair are now avoided in source function
 @('assume-true-false-rec').)  Thanks to Eric Smith for pointing out
 that there can be type-alists with many consecutive identical entries.</p>

 <p>Sped up macroexpansion for several common macros, with roughly a 2% to 3%
 speedup observed for including several large books during development of this
 change.</p>

 <p>Tweaked @(see linear-arithmetic) to avoid consideration of an equality
 between two terms that are both known (via their @(see type-set)s) to be
 non-numeric.</p>

 <p>The utility @(tsee set-cbd) is more efficient when setting to the current
 @(tsee cbd), including the common case of calls to @('set-cbd') by @(tsee ld)
 and (hence) @(tsee wormhole).</p>

 <p>New built-in @(see rewrite) rules @('all-boundp-initial-global-table-alt')
 and @('all-boundp-initial-global-table') may help with reasoning about
 @('state-p1').  Use @(':')@(tsee pe) to see their @(see events).  The latter
 is @(see disable)d by default and may useful to @(see enable) when developing
 proofs that rely on built-in @(see state) globals being bound.</p>

 <p>ACL2 has a procedure for evaluating ground @(see term)s (terms without free
 variables) that is used in the generation of @(see guard) obligations as well
 as in @(see linear-arithmetic) and @(see forward-chaining).  This procedure
 was not used on subterms of bodies of @(see lambda) expressions, but now it
 is.  Thanks to Eric Smith for requesting this enhancement (in particular for
 generation of guard obligations).</p>

 <p>The ACL2 @(see type-reasoning) mechanism has been strengthened slightly for
 an @('if') expression being assumed true or false, when that expression has a
 subterm of the form @('(equal term 'c)'), or @('(equal 'c term)') and @('c')
 is @('0'), @('1'), @('t'), or @('nil').  Thanks to Warren Hunt for sending an
 example involving @(see forward-chaining) that led to this improvement.
 <b>IMPORTANT NOTE:</b> If this change causes a proof to fail that formerly
 succeeded, you can fix it by preceding it with the following (implicitly @(see
 local)) event.</p>

 @({
 (defattach-system use-enhanced-recognizer constant-nil-function-arity-0)
 })

 <p>For a book's event of the form @('(defconst *NAME* (quote VAL))') that
 results from @(tsee make-event) expansion, @('VAL') is no longer duplicated
 between that book's @(see certificate) file and its compiled file.  Thanks to
 Sol Swords for requesting this enhancement.  This lack of duplication also
 applies to any such @('defconst') event in a book that is in the scope of a
 @(tsee progn) or @(tsee encapsulate) event when there is at most one
 @('make-event') call in that scope; similarly for such @('defconst') events
 within calls of @(tsee skip-proofs), @(tsee with-output), @(tsee
 with-guard-checking), or @(tsee with-prover-step-limit).</p>

 <p>Each new stobj was being created twice at @(tsee include-book) time, once
 when the book's compiled file is loaded and once when the @(tsee defstobj) or
 @(tsee defabsstobj) event is processed.  The former initialization is
 unnecessary and has been eliminated.</p>

 <p>A limit has been placed on generation of equality hypotheses by linear
 arithmetic.  For example, if a goal has hypotheses (technically: negative
 literals) @('(<= term1 term2)') and @('(<= term2 term1)'), it may generate the
 hypothesis @('(equal term1 term2)').  This is now indicated by the phrase
 "equality generation from inequalities" found in proof output if you have
 evaluated the form @('(set-gag-mode nil)'), and it is now indicated in the
 proof @(see summary) by the presence of the @(see rune),
 @('(:FAKE-RUNE-FOR-LINEAR-EQUALITIES NIL)').  By default, there is a limit of
 five &ldquo;levels&rdquo; of such equality generation, for example in goals
 @('"Subgoal 2"'), @('"Subgoal 2.1"'), @('"Subgoal 2.1.3.4.5"'),
 @('"Subgoal 2.1.3.4.5'"'), and @('"Subgoal 2.1.3.4.5''"') &mdash; in
 general, such addition of equalities can only be performed five times along a
 chain of goals where each is a descendant (not necessarily an immediate
 subgoal) of the one before, and each induction and forcing round provides a
 fresh start.  You can change that default from 5 to @('n'), where @('n') is a
 natural number, by evaluating the following form.</p>

 @({
 (table equational-polyp-limit-table t n)
 })

 <p>Thanks to Eric Smith for sending an example with looping behavior, which
 motivated the change above (as a way to break such loops).</p>

 <h3>Bug Fixes</h3>

 <p>Fixed a soundness bug based on rules of class @(':')@(tsee meta) or
 @(':')@(tsee clause-processor) that would be exported from an @(tsee
 encapsulate) event with a non-@('nil') @(see signature) list.  A proof of
 @('nil') in Version  8.5 may be found in the @(see community-books) file,
 @('books/system/tests/transparent-functions-input.lsp'); search for
 this paragraph there.</p>

 <p>Fixed a soundness bug in @(tsee open-input-channel) and @(tsee
 open-output-channel).  The @(see guard) in each case required the first
 argument, a file name, to be a string; but these functions pass that argument
 to a function &mdash; @('make-input-channel') and @('make-output-channel'),
 respectively &mdash; that required the string to contain only standard
 characters (see @(see standard-char-p)).  That was possible because
 @('open-input-channel') and @('open-output-channel') were invoked under @(tsee
 skip-proofs) in the ACL2 sources.  This bug has been fixed, and those uses of
 @('skip-proofs') eliminated, with removal of the restriction to standard
 characters for virtually all guards, including the guards for Common Lisp
 functions @(tsee char-downcase) and @(tsee char-upcase).  Thanks to Eric Smith
 for reporting this bug, including a proof of @('nil') by giving a @(':use')
 hint for an @(':instance') of @('(:guard-theorem open-input-channel)').  Eric
 also supplied events, incorporated into ACL2 source file @('axioms.lisp'),
 that removed the @(tsee skip-proofs) wrappers from five definitions.</p>

 <p>Fixed a soundness bug that exploited incorrect generation of raw Lisp code
 for the recognizer of a @(see stobj) field of a stobj.  More precisely, the
 bug occurred when a concrete stobj has a field whose type is the name of
 either a concrete or abstract stobj.  Here is an example.</p>

 <blockquote>

 <p>First certify the following book, sub.lisp.</p>

 @({
 (in-package "ACL2")
 (defstobj lo lo-fld)
 (defstobj hi (hi-fld :type lo))
 })

 <p>Then before the bug was fixed, the following book was certifiable.</p>

 @({
 (in-package "ACL2")
 (include-book "sub")
 (defthm thm1 ; logically correct
   (hi-fldp '(nil))
   :rule-classes nil
   :hints (("Goal" :in-theory (disable (:e hi-fldp)))))
 (defthm thm2 ; "proved" by unsound execution
   (not (hi-fldp '(nil)))
   :rule-classes nil)
 (thm ; proof of nil
  nil
  :hints (("Goal" :use (thm1 thm2))))
 })

 </blockquote>

 <p>It was probably a soundness bug to allow a @(tsee defaxiom) event to
 designate a rule of class @(':')@(tsee meta) or @(':')@(tsee clause-processor)
 in its @(':')@(tsee rule-classes).  That is no longer allowed; @(tsee
 skip-proofs) may be used instead if one believes that the proposed formula is
 a theorem.</p>

 <p>The function @(tsee read-file-into-string) has been modified to avoid what
 might be considered a soundness bug.  The change involves causing an error for
 two reads of the same file without first incrementing the file-clock of the
 @(see state).  See @(see read-file-into-string) for details, in particular for
 how to avoid that error by evaluating @('(increment-file-clock state)') after
 calling @('read-file-into-string').  Formerly the error was avoided if the
 write-date of the file didn't change between the two reads, but the following
 example shows how this permitted two calls with identical arguments to produce
 different results, logically causing @('read-file-into-string') to violate the
 axiom @('x = x').</p>

 <blockquote>

 <p>First run the following shell commands.</p>

 @({
 echo 'test1' > tmp1.txt ; echo 'test2' > tmp2.txt
 cp -p tmp1.txt tmp.txt
 })

 <p>Then start ACL2 and run a command as follows.</p>

 @({
 ACL2 !>(read-file-into-string "tmp.txt")
 "test1
 "
 ACL2 !>
 })

 <p>Now suspend ACL2 with @('control-Z') and run the following shell
 command.</p>

 @({
 cp -p tmp2.txt tmp.txt
 })

 <p>Now resume ACL2 with @('fg'), and optionally submit some trivial form (say,
 @('3')) just to get the prompt back.  Note that the file-clock of the
 @('state') hasn't changed.  (Probably the @('state') hasn't changed; at any
 rate, the parts of the state relevant to @('read-file-into-string') haven't
 changed.)  So the following call has arguments identical to those in the
 corresponding call above, yet yields a different result.</p>

 @({
 ACL2 !>(read-file-into-string "tmp.txt")
 "test2
 "
 ACL2 !>
 })

 <p>After the change to @('read-file-into-string'), its call just above causes
 an error.</p>

 </blockquote>

 <p>Plugged a potential soundness hole in @(tsee defwarrant) (though we have
 not actually observed unsoundness), with changes that will probably be
 invisible to users.  Thanks to Sol Swords for bringing this issue to our
 attention.</p>

 <p>Fixed a bug in system function @('bounded-integer-listp'), which may have
 allowed illegal @(see proof-builder) commands to be attempted.  Thanks to
 Grant Jurgensen for pointing out this bug.</p>

 <p>Consider calls of @(tsee defthm) and @(tsee thm) that create subgoals
 before reverting to prove the original goal by induction.  The Rules summary
 printed at the end should exclude rules used only before the start of that
 induction proof.  That was formerly the case for @('defthm') but not @('thm'),
 but now it is the case for both.  You can see the change for the following
 call, whose Rules summary formerly included @('(:ELIM CAR-CDR-ELIM)') but no
 longer does so.</p>

 @({
 (thm
  (equal (append (append x y) z)
         (append x y z))
  :hints (("Goal"
           :expand ((:free (b) (append x b))
                    (:free (a b) (append (cons (car x) a) b))))))
 })

 <p>Fixed bugs in the definition of source macro @('position-ac').  Thanks
 to Eric Smith for pointing them out.</p>

 <p>Several improvements were made to the @('FOR') @(tsee loop$) utility (also
 see @(see for-loop$), to reflect more accurately the Common Lisp @('loop')
 utility.  This matters because in @(see guard)-verified code, @('loop$')
 becomes @('loop').  Here are the most user-visible such changes.</p>

 <ul>

 <li>Run-time @(see guard)-checking for @(tsee loop$) operators @('SUM') and
 @('APPEND') did not include a check that the value produced at each iteration
 is a number or true list, respectively.  That has been fixed so that, for
 example, the expression @('(loop$ for v in '(1 a 2) sum v)') now causes a
 guard violation (because @('a') is not a number), where previously it did
 not.</li>

 <li>For a form @('(loop$ for tail on lst ...)'), the target term, @('lst'), no
 longer needs to satisfy @(tsee true-listp).  For example, the form @('(loop$
 for tail on '(a b . c) collect tail)') no longer causes a @(see guard)
 violation.</li>

 <li>Run-time @(see guard)-checking for an expression @('(loop$ for tail on lst
 ...)') now includes a check for the target, @('lst'), that its final
 tail (i.e., @('(last-cdr lst)')) satisfies the declared type of the
 corresponding iteration variable.  For example, evaluation of the @(tsee
 loop$) expression below now produces a guard violation as shown, but it
 formerly did not produce a guard violation.

 @({
 ACL2 !>(loop$ for tail of-type cons on '(a b c) collect tail)


 ACL2 Error [Evaluation] in TOP-LEVEL:  The guard condition
 (CONSP LOOP$-LAST-CDR), which was generated from a type declaration,
 has failed.
 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 !>
 })

 Corresponding run-time checking was added for the types of the lower and upper
 bounds @('lo') and @('hi'), the increment @('inc'), and the last value tested,
 in expressions @('(loop$ for i from lo to hi by inc ...)').</li>

 </ul>

 <p>Fixed a low-level bug in source function
 @('translate-declaration-to-guard1-gen') that was incorrectly creating
 untranslated @(see term)s in some cases from @(see type) declarations of the
 form @('(type (signed-byte _) _)') or @('(type (unsigned-byte _) _)').  Here
 is an example of an event that is rejected without the bug fix.</p>

 @({
 (defun foo (n)
   (apply$ (lambda$ (x)
                    (declare (type (signed-byte 8) x)
                             (xargs :guard (signed-byte-p 8 x) :split-types t))
                    (+ 3 x))
           (nfix n)))
 })

 <p>Suppose a book is certified in a @(see world) where a @(see portcullis)
 @(see command) generates a @(tsee local) call of @(tsee make-event).  Then
 that event is now ignored when subsequently including that book.  Previously
 it may not have been ignored, because the @('local') wrapper could be ignored
 when writing the book's @(see certificate).</p>

 <p>Some handling of exceptional cases in @(see hints) has been cleaned up, as
 follows.  Thanks to Eric Smith for a discussion that led to these changes.</p>

 <ul>

 <li>@(csee Warnings) for repeating a goal name in the hints now appear even
 when the repetition is only up to case.  For example, such a warning is
 generated now for @(':hints (("Goal" :use foo) ("GOAL" :use bar))') where
 formerly it was not.  The discussion of this situation in documentation topic
 @(see hints) has been improved.</li>

 <li>It was incorrectly documented in topic @(see hints), in the discussion
 of @(':do-not') hints, that it is illegal to associate a goal name with the
 empty list of @(see hints), as in @('("Goal")').  This behavior was actually
 allowed; an empty such hint was simply ignored.  This continues to be
 allowed (for backward compatibility) but the documentation has been updated;
 also, these empty hints are now ignored for purposes of the warnings mentioned
 above (formerly they were considered when looking for repetition of goal
 names).</li>

 </ul>

 <p>A bug in the @(see brr) commands @(':eval$'), @(':go$'), and @(':ok$') was
 fixed so they now behave as described in the documentation for @(see
 brr-commands).</p>

 <p>When a certified book is included, the logical @(see world) will no longer
 be marked as having seen a @(tsee skip-proofs) call due to @(tsee LD) special
 @(tsee ld-skip-proofsp) having a non-@('nil') value at that time.  Thus, that
 situation no longer disqualifies such a world from supplying the @(see
 portcullis) commands to a book to be certified without keyword argument
 @(':skip-proofs-okp t') of @(tsee certify-book).  Thanks to Sol Swords for
 pointing out this bug.</p>

 <p>Fixed a bug that was causing calls of @(tsee wormhole) to signal an
 error.</p>

 <p>Fixed a bug that could cause a @(tsee do-loop$) expressions to be
 inappropriately rejected due to an allegedly ignored variable.  An example is
 below.</p>

 @({
 (include-book "projects/apply/top" :dir :system)
 ; BUG: The following was formerly necessary, but no longer is.
 (set-ignore-ok t)
 (defun f (a b)
   (loop$ with x = a with y = b
          do
 ; The use of (set-ignore-ok t) was needed, but shouldn't have been,
 ; whether or not the next line is included.
          :measure (+ (len x) (len y))
          (cond ((consp y)
                 (let ((z y))
                   (progn (setq y (cdr x))
                          (setq x (cdr z)))))
                (t (return y)))))
 })

 <p>Fixed the failed redundancy check when setting a @(see table) guard that
 returns two values.  For example, the form @('(table foo nil nil :guard (mv t
 nil))') was not formerly seen as @(see redundant) when evaluating it a second
 time.</p>

 <p>Fixed a bug that was causing @(tsee cw-gstack) to report
 &ldquo;Rewriting (to simplify) the first argument&rdquo; when rewriting the
 second argument of a call of @(tsee implies), and fixed an analogous bug for
 @(tsee return-last).</p>

 <p>Fixed a bug in @(tsee intersection$) that prevented it from being called
 with keyword argument @(':test 'equal').  Thanks to Anna Slobodova for
 bringing this bug to our attention.</p>

 <p>Certain error messages from @(tsee translate) and @(tsee untranslate) are
 now inhibited when they should be (where formerly they weren't).  Thanks to
 Eric Smith for bringing this problem to our attention.</p>

 <p>Fixed a bug that in rare cases, for direct prover calls (e.g., with @(tsee
 prove$), could cause an error reporting &ldquo;HARD ACL2 ERROR in
 pop-warning-frame&rdquo;.  Thanks to Eric Smith for bringing this bug to our
 attention.  Note that with this change, then when an @(see event)'s evaluation
 causes a hard error (see @(see er) and @(see hard-error)): @(see summary)
 information may be printed that was formerly omitted; and a superfluous extra
 failure message may be omitted that was formerly printed.</p>

 <p>The function @(tsee delete-file$) executed in a way that diverged from its
 logical definition: successful deletion caused return values of @('(mv t
 state)') but this was provably impossible according to the logical
 definition.  This has been fixed.</p>

 <p>Fixed the @(see useless-runes) feature to work properly when reading a
 useless-runes file while certifying a book in a package other than the
 @('"ACL2"') package.  The fix is to ensure that the useless-runes file is
 read while in the @('"ACL2"') package, which is the same package used when
 the file was written.</p>

 <p>Fixed a bug in handling of the @(tsee ld) keyword
 @(':ld-missing-input-ok'), by eliminating an error in the case that the
 specified input file's directory does not exist.  The fix avoids executing
 some of the @('ld') code that was formerly executed.  Thanks to Alessandro
 Coglio and Eric Smith for bringing this bug to our attention.</p>

 <p>An error formerly occurred if one first evaluated @('(defwarrant FN)') for
 some @('FN') and then attempted to include a certified book containing
 @('(defbadge FN)').  That has been fixed.  Thanks to Mertcan Temel for
 reporting this bug.  Such a @(tsee defbadge) event is now a no-op, which is
 reported by an @(tsee observation) except during @(tsee include-book) and
 except during the second pass of an @(tsee encapsulate) event.  Moreover, the
 @(tsee defwarrant) event now returns the value @(':WARRANTED') instead of
 @('T') &mdash; more precisely, it returns a @(see value-triple) whose value
 component is @(':WARRANTED') &mdash; and similarly for @(tsee defbadge) and
 @(':BADGED').</p>

 <p>We fixed a bug that caused the @(see tau-system) sometimes to cause a raw
 Lisp error when the @(see executable-counterpart)s of certain primitive
 recognizers were @(see disable)d.  Thanks to Eric Smith for reporting this bug
 and providing an example of it.</p>

 <p>We fixed a bug that might cause suitable induction schemes to be eliminated
 because of inappropriate consideration of @(':')@(tsee definition) rules.</p>

 <p>Some @(see proof-builder) commands, including @(':claim') and
 @(':casesplit'), are more robust (specifically, when claiming or splitting on
 certain terms that are trivially true).  Thanks to Drew Walter for supplying
 an illustrative example.</p>

 <p>A bug in @(tsee trace$) could trigger raw Lisp errors when the @(':entry'),
 @(':exit'), or @(':cond') option specified an ill-guarded expression.  For
 example, after evaluating @('(defun f (x) x)') and then @('(trace$ (f :entry
 (car x)))'), evaluation of @('(f 3)') caused a raw Lisp error due to
 evaluation of @(tsee car) on the value, 3.  This has been fixed.  (Technical
 Remark: the fix was to replace the expression with the same
 &ldquo;oneify&rdquo; process that is used for generating definitions of
 executable-counterpart functions; @(see evaluation).)</p>

 <p>Eliminated the built-in @(':')@(tsee type-prescription) rule
 @('true-listp-take'), thanks to Eric Smith, who pointed out that the same rule
 is already installed as the built-in @(':type-prescription') rule for @(tsee
 take).</p>

 <p>Fixed a bug in handling of @(tsee do-loop$) expressions that return
 multiple values, when encountered during proofs.  An example labeled with
 &ldquo;Version 8.5&rdquo; is near the end of @(see community-book)
 @('projects/apply/loop-tests.lisp').</p>

 <p>A bug in @(tsee do$), hence in @(tsee do-loop$) expressions, was that
 single-threadedness (for @(see stobj)-based computations) can be violated when
 a loop terminates prematurely because the measure fails to decrease.  The bug,
 which has been fixed, is explained in detail in a comment in ACL2 source file
 @('apply.lisp'), entitled &ldquo;About a bug in DO$ in ACL2
 Version  8.5&rdquo;.</p>

 <p>Fixed a bug in @(tsee fmt) and related functions, where a right square
 bracket immediately following a @('~&') or @('~v') directive failed to be
 printed, for example: @('(fmx "hello ~&0]~|" '(world))').</p>

 <p>Fixed a bug that could cause an implementation error during a proof, when
 printing a term with a @(tsee do$) call.  (The bug was in untranslating
 certain applications of @(tsee nth), @(tsee update-nth), or @(tsee
 update-nth-array) during a proof.)</p>

 <p>@(tsee With-global-stobj) no longer produces an invalid result when its
 first argument names a non-executable @(see stobj).  Previously, the call of
 @('read-state') below could return the nonsensical result 637624320.</p>

 @({
 (defstobj st fld :non-executable t)
 (defun read-state (state)
   (declare (xargs :stobjs state))
   (with-global-stobj st (fld st)))
 (read-state state)
 })

 <p>Fixed two bugs when attempting to redefine with @(tsee defabsstobj).  The
 visible bug was a printing error.  A second bug, not visible to the user
 because of the first bug, was a low-level bug that prevented one of the
 supporting names from being recorded in the @(see world) as a supporter of the
 given stobj.</p>

 <h3>Changes at the System Level</h3>

 <p>The `@('make')' target, @('save-exec'), now builds @('custom-saved_acl2')
 unconditionally.  Thanks to Grant Jurgensen for pointing out (in GitHub Issue
 #1422) that there can be untracked implicit dependencies that make this
 necessary.</p>

 <p>Implementations underlying the functions @(tsee sys-call), @(tsee
 sys-call+), and @(tsee sys-call*) have been cleaned up.  In particular, we now
 expect them to indicate precisely the case of a non-error process return as
 follows: 0 for @(tsee sys-call-status), and @('nil') for the first return
 value of @('sys-call+') and @('sys-call*').  Also, a bug has been fixed for
 @('sys-call+') in the case of GCL as the host Lisp.  Thanks to Eric Smith
 for queries leading to these changes.</p>

 <p>Significantly extended documentation topic @(see system-attachments), which
 now lists all built-in system attachments, many with brief documentation.
 Thanks to Eric Smith for suggesting this enhancement.</p>

 <p>Significant new @(see documentation) topics, together with subtopics and
 books supporting those topics, include the following.  [See DARPA Note
 above.]</p>

 <ul>

 <li>@(see Start-here) provides a guide for those getting started with
 ACL2.</li>

 <li>@(see Recursion-and-induction) has been extensively modified from past,
 standalone versions by J Moore, and is now integrated with the rest of the
 @(see documentation).  Thanks to Vivek Ramanathan for helpful feedback.</li>

 <li>@(see Gentle-introduction-to-acl2-programming) has also been updated from
 past standalone versions and integrated into the rest of the
 documentation.</li>

 <li>@(see Loop$-primer) provides an extensive primer on the ACL2 @(tsee loop$)
 feature.</li>

 <li>@(see Type-reasoning) gives a basic introduction to what has sometimes
 been called ``type-set reasoning'' but is now generally referred to as
 &ldquo;type reasoning&rdquo;.  This new topic is now referenced in many other
 built-in documentation topics.  Thanks to Warren Hunt for communication
 leading to this new topic.</li>

 <li>@(see Soundness) discusses what we can conclude when we use ACL2 to prove
 a formula or to compute the value of an expression.</li>

 </ul>

 <p>Allow @(tsee ld) output in @(see raw-mode) to go to other than the channel,
 @('*standard-co*').  Thanks to Vivek Ramanathan and Warren Hunt for an example
 illustrating the issue.</p>

 <p>(For system hackers only) The feature @(':acl2-loop-only') is now true
 inside the ACL2 read-eval-print loop.  Therefore, the function @('lp!') is no
 longer supported or necessary, since @('(lp)') enters the loop with feature
 @(':acl2-loop-only') true, just as @('(lp!)') did previously.</p>

 <p>(CCL only) @(csee Stobj) array code now has a workaround for a <a
 href='https://github.com/Clozure/ccl/issues/446'>CCL bug</a> found by Yahya
 Sohail, in the case of reading a stobj array of integers where the element
 type includes at least one negative number and one non-fixnum.  That bug has
 been around since at least as far back as 2017, and was fixed on June 12,
 2023.  For those using a CCL version with the bug, this fix may slow down such
 stobj array reads a bit in the case described above; one measurement showed
 about 37% more time for such a read.  Thanks to Yahya for the bug report, to
 Warren Hunt for encouraging a workaround, and to the CCL developers (in
 particular Gary Palter) for fixing the CCL bug.</p>

 <p>The undocumented utility, @('thm-fn') &mdash; which is used in several
 @(see community-books) &mdash; now has an additional formal (at the end),
 @('event-form').  That argument can generally be passed as @('nil') for
 appropriate behavior.</p>

 <p>Code for @(tsee set-cbd) has been tweaked to add assurance that the @(tsee
 cbd) always ends in a forward slash (&lsquo;@('/')&rsquo;), as specified.
 Thanks to Stephen Westfold for a comment leading to this modification.</p>

 <p>Updated file @('GNUmakefile') in the top-level directory so that when an
 ACL2 executable is built, files are updated in subdirectory @('books/build/')
 to support the use of @(tsee build::cert.pl).  Thanks to Eric Smith for the
 idea, and thanks to Eric and also Sol Swords for help with the
 implementation.</p>

 <p>The notion of ACL2 @(see state) is formalized in function @('state-p1'),
 which has implicitly changed because it depends on the constant
 @('*initial-global-table*'), whose value has changed.  That constant's value,
 which is still an alist, now includes additional pairs, which are from the
 constant @('*initial-ld-special-bindings*'); thus, @('*initial-global-table*')
 now specifies a value for each so-called &ldquo;@(tsee ld) special&rdquo;.</p>

 <p>The previous ACL2 release (Version  8.5) arranged that when a raw Lisp
 error is encountered, any available input is cleared from the input channel.
 However, this can lead to discarding of valid input or an attempt to read
 values from within a comment; see @(see community-books) files
 @('clear-input-1.lsp') and @('clear-input-2.lsp'), respectively, in directory
 @('books/system/tests/').  So now, input is cleared on error only when reading
 from the terminal (technically, from @(tsee *standard-oi*)).</p>

 <p>Improved certain build-time error messages.  These improvements are
 particularly helpful when the host Lisp is SBCL or CMUCL, so that the error
 message is printed properly into make.log (instead of showing up as an error
 call at the terminal), and also when the host Lisp is LispWorks, so that
 verbose debugging information is avoided (since these are ACL2 errors for
 which that information is very unlikely to be helpful).  Thanks to Alessandro
 Coglio for a recent Zulip query that led us to make this change.</p>

 <p>A new documentation topic and its subtopics describe uses of ACL2 and its
 predecessor, Nqthm, in modeling state machines.  See @(see
 operational-semantics), which notes that others are welcome to add to these
 topics; see the discussion of &ldquo;Request for Suggestions from ACL2
 Users&rdquo;.  The new topic incorporates an annotated bibliography pointing
 to more than 40 topics in a new @('"BIB"') package.</p>

 <h3>EMACS Support</h3>

 <p>A set of tools for assisting in the conversion of certain HTML to @(tsee
 XDOC) may be found, without much documentation, in @('emacs/html-to-xdoc.el').
 [See DARPA Note above.]</p>

 <p>When new @(see acl2-doc) buffers are created by using the @('G') or
 @('Shift-<Return>') commands, their name reflects the topic name, e.g.,
 @('acl2-doc<REWRITE>') if the topic visited in the new buffer is @('REWRITE').
 Note that the new buffer name stays the same even if other topics are visited
 there; its name reflects its topic at the time it was created.  Thanks to
 Warren Hunt for requesting such an enhancement.  Note that the former behavior
 can be restored by evaluating the form @('(setq
 *acl2-doc-short-new-buffer-names* t)') in Emacs.</p>

 <p>The initialization file for recent Emacs versions,
 @('books/emacs/emacs-acl2.el'), now correctly loads related files &mdash;
 notably @('acl2-doc.el') &mdash; from that same directory, rather than from
 the @('emacs/') directory that is directly under the top level of the ACL2
 distribution.</p>

 <p>@(csee Documentation) printed to the terminal or in the @(see ACL2-Doc)
 Emacs browser can respect certain @(see xdoc::markup) that was formerly
 ignored, but is no longer (by default), as follows.</p>

 <ul>

 <li>Fonts are largely respected.  For example, text marked as underline is now
 underlined, and text marked as having typewriter font now has a grey
 background.  This closes GitHub Issue 1487.  Thanks to Grant Jurgensen for
 helpful feedback on the original plan, which had been to use delimiting
 underscores rather than Select Graphic Rendition (SGR) control sequences.  See
 @(see xdoc::terminal) for details and for ways to customize behavior,
 including avoidance of SGR.</li>

 <li>Images now appear in @(see ACL2-Doc) (but not with @(':')@('doc') at the
 terminal), instead of @('{IMAGE}'), on systems that can display graphics
 inside Emacs.  Thanks to Warren Hunt for requesting this enhancement.</li>

 </ul>

 <p>The documentation for @(see ACL2-Doc) says of the search commands @('s')
 and @('S'), &ldquo;go to that topic with the cursor put immediately after the
 found text&rdquo;.  But the cursor was at the end of the found text, not
 immediately after it.  That has been fixed.</p>

 <p>For the @(see acl2-doc) browser, the download (@('D')) command now
 accesses, by default, an @('https') address instead of an @('http') address.
 Thanks to Warren Hunt for suggesting this change.</p>

 <p>In @(see acl2-doc), modified the @('TAB') and @('Shift-TAB') (sometimes
 known as @('<backtab>')) commands so that they alert the user when
 wrapping.</p>

 <h3>Experimental Versions</h3>

 <p>The note &ldquo;Note: No checkpoints to print.&rdquo; that might be printed
 on proof failure is now the same in ACL2(p) as in ACL2, unless @(see
 waterfall-parallelism) is enabled (in which case &ldquo;no checkpoints&rdquo;
 is followed by &ldquo; from gag-mode&rdquo; as before).</p>

 ")
other
(defxdoc note-8-7
  :parents (release-notes)
  :short "ACL2 Version  8.7 (xxx, 20xx) 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  8.6 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-7-books) for a summary of changes made to the ACL2 Community Books
 since ACL2  8.6, including the build system.</p>

 <h3>Changes to Existing Features</h3>

 <p>The output generated by the induction routine has been slightly changed.
 Now, if term @('t0') suggested the induction scheme but other terms, @('t1'),
 ... @('tk'), either suggested the same scheme or schemes that merged with
 @('t0')'s to create the selected scheme, the induction output includes the
 sentence ``@('We will induct according to a scheme suggested by t0, while
 accommodating t1, ..., tk')''.  The terms mentioned are all preferentially
 expanded by the simplifier when they arise in the subgoals produced by that
 induction.  The fact that the terms are preferentially expanded is not new.
 What's new is that ACL2 now lists all the accommodated terms.</p>

 <p>When the @(see summary) prints &ldquo;Modified system attachments&rdquo;,
 it now sorts that information before printing it.</p>

 <p>Improved the error message when the package name is missing immediately
 after `#!', as in #!(foo).</p>

 <p>It was the case that in an @(see event) @('(add-macro-alias mac fn)'),
 @('(add-macro-fn mac fn)'), or @('(add-binop mac fn)'), if @('fn') was a macro
 name then this event generally had no effect.  Now, if in addition an event
 @('(add-macro-alias fn fn2)') has first been admitted (and no later such event
 has been admitted), then in these three events, @('fn') will be treated as
 @('fn2').  See @(see add-macro-alias).  Thanks to Grant Jurgensen for sending
 an example that showed how a confusing @(tsee in-theory) error could occur
 before this change, in the situation described above: after the change,
 @('(in-theory (disable mac))') is treated as a directive to @(see disable)
 @('fn2'); but before the change it was treated as an attempt to @(see disable)
 the macro, @('fn'), which caused an error.</p>

 <p>The utility @(':')@(tsee trans*) new uses the @(':TERM') @(see evisc-tuple)
 (see @(see set-evisc-tuple)) to print terms, as was already being done by
 @(':')@(tsee trans).</p>

 <p>The behavior and documentation for @(tsee read-file-into-string) have been
 cleaned up and put in sync.  Thanks to Eric Smith and Grant Jurgensen for
 communication that led to these improvements.</p>

 <h3>New Features</h3>

 <p>The new function symbol @('strict-table-guard') returns its single argument
 unchanged, but has a special meaning when a @(see table)'s @(':guard') is a
 call of that function symbol.  In that case, a term supplied for updating the
 table &mdash; that is, for the @(':put') and @(':clear') operations &mdash;
 must have no free variables, even though variables @('WORLD') and @('ENS') are
 normally permitted.  See @(see table).</p>

 <p>A new feature provides ways to stop certain infinite loops in the
 waterfall.  It is now possible to specify a limit on how many times the
 waterfall can produce a new subgoal along a branch.  It is also possible to
 specify that the prover should check for ``simple'' loops in the waterfall.
 The default setting for this new feature limits the branch length to 1000 and
 enables checking for duplicate goals.  See @(tsee
 set-subgoal-loop-limits) for details.  Thanks to Eric Smith for suggesting
 that we consider supporting loop detection at the goal level.</p>

 <p>A new feature provides help in debugging failed proofs involving functional
 instantiation.  In particular, it helps you answer the question ``where did
 this subgoal come from?'' when looking at a subgoal produced by functionally
 instantiating a constraint.  See @(tsee
 set-constraint-tracking).</p>

 <h3>Heuristic and Efficiency Improvements</h3>

 <p>Applications that use functions with floating-point inputs or outputs (see
 @(see df)) may generate less memory usage, at least in SBCL releases strictly
 after SBCL Version 2.9 and SBCL github versions after mid-October, 2024.
 Thanks to Stas Boukarev for enhancing SBCL to support this improvement (made
 by adding suitable proclaiming in ACL2).</p>

 <p>Avoided a potential quadratic blowup in @(see guard) generation by
 improving how guard obligations are simplified.  Specifically, improved the
 simplification of ground subterms so that @('(if x y y)') can simplify to
 @('y'); other uses in ACL2 of ground subterm simplification similarly benefit.
 Thanks to Eric Smith for sending the following example, which now generates a
 simpler guard proof obligation.</p>

 @({
 (defun foo (x y)
   (declare (xargs :guard t))
   (let ((x (+ 1 x)))
     (case x
       (1 (natp x))
       (2 (consp x))
       (3 (rationalp x))
       (otherwise (+ x y)))))
 })

 <p>Sped up @(tsee include-book) by significantly reducing time in translating
 calls of @(tsee with-output) and some other macros (for some technical details
 see ACL2 source function @('macroexpand1*-cmp')) and in creatiion of the
 so-called post-alist in a @(see certificate) (for relevant code, which shows
 the use of @(see fast-alists), see ACL2 source function
 @('accumulate-post-alist')).  For examples showing reduction by about 1/3 in
 include-book time, see the comment &ldquo;Here are sample time reports (...)
 for include-book speedups due to...&rdquo; in the form @('(defxdoc note-8-7
 ...)') in @(see community-book) @('books/system/doc/acl2-doc.lisp').  Thanks
 to Eric Smith for sending an example book for which to speed up @(tsee
 include-book).</p>

 <p>When a function, constant, or macro was defined within an @(tsee
 encapsulate) form, its definition was evaluated in Lisp with each pass of
 evaluating the @('encapsulate') form, and similarly for the definition of its
 executable-counterpart (see @(see evaluation)).  For CCL and SBCL, that
 implies that such function definitions were compiled with each pass.  Now,
 with a few exceptions, these definitions are saved in the first pass of
 evaluating the @('encapsulate') form and retrieved, rather than re-evaluated,
 in the second pass.  The exceptions include the following.

 <ul>

 <li>No definition is stored or retrieved that is within the scope of an
 @('encapsulate') form with a non-empty list of @(see signature)s.</li>

 <li>No definition of the executable-counterpart of a function symbol is
 retrieved when that symbol has a non-redundant @(see logic)-mode definition in
 the scope of @(tsee local) that was evaluated within the first pass of the
 same @('encapsulate').</li>

 <li>No @(see local) definition is stored that is within two or more nested
 @('encapsulate') events.</li>

 </ul>

 Thanks to Eric Smith for asking if a function defined within an encapsulate
 can be expected to be compiled twice, once for each pass of the encapsulate.
 Implementation-level details are explained in the section entitled
 &ldquo;Appendix 2: Extension for Encapsulate&rdquo; in the ACL2 source code
 comment, &ldquo;Essay on Hash Table Support for Compilation&rdquo;.  In
 particular, the end of that Essay discusses an enhancement that saves compiled
 code for redundant @('defun')s.</p>

 <h3>Bug Fixes</h3>

 <p>Fixed a soundness bug in the @(see proof-builder) that could cause goals
 from @(tsee force)d hypotheses to be created incorrectly.  (This bug has been
 around for at least 10 years and probably for 30 years!)</p>

 <p>Fixed a soundness bug based on the use of @(tsee swap-stobjs) on two @(see
 stobj)s of which one is &ldquo;live&rdquo;.  See @(see live-stobj-in-proof).
 Thanks to Sol Swords for reporting this bug, including an example and analysis
 of possible fixes in his report.  (Technical Note.  We have added code to
 check for live @(see stobj)s in proofs, which was sufficient to fix the bug.
 But the situation described above is caught by a change to @('swap-stobjs'),
 which now signals an error in the relevant case (exactly one live stobj
 input).)</p>

 <p>Fixed a soundness bug due to the interaction of @(see stobj)s and @(tsee
 defattach).  The fundamental problem was that @('defattach') events can cause
 a stobj recognizer to become false; see @(see community-book)
 @('books/system/tests/stobj-attach-unsoundness.lisp').  The solution is to
 disallow attachments for certain supporters of stobj primitives; see @(see
 stobj-attachment-restrictions).  Thanks to Sol Swords for reporting the bug,
 analyzing it quite thoroughly, contributing the book mentioned above,
 modifying other books as necessary, and providing preliminary code to fix the
 bug, and for helpful conversations.</p>

 <p>A Lisp error is now avoided when saving event-data (see @(see
 saving-event-data) and submitting certain ill-formed attempts at @(see
 events).  Thanks to Eric Smith for sending the following example.</p>

 @({
 (assign event-data-fal 'event-data-fal)
 (defuns foo (x) x)
 })

 <p>Fixed a bug in the interaction of @(tsee memoize-partial) with utilities
 @(tsee save-and-clear-memoization-settings) and @(tsee
 restore-memoization-settings).  The latter utilities no longer have an effect
 on functions created by @(tsee memoize-partial) (or, and this is quite
 obscure, on memoization from calls of @(tsee memoize) with a non-@('nil')
 value of the keyword, @(':total')).</p>

 <p>An attachable stobj (see @(see attach-stobj)) was created by the
 executable (@(':EXEC')) function associated with its stobj creator (see @(see
 defabsstobj)), even when that stobj was given an attachment.  This bug has
 been fixed: the stobj is now created by the @(':EXEC') of the attachment's
 creator.</p>

 <p>Fixed a bug in @(tsee trans*) when its use encounters a call of @(tsee
 make-event) with the @(':on-behalf-of') keyword.  Thanks to Grant Jurgensen
 for reporting this bug using a simple example.</p>

 <p>According to the documentation for @(tsee table), the variable @('ENS') is
 allowed in both the key and value expressions when updating the table, that
 is, using the @(':put') and @(':clear') operations.  However, @('ENS') was not
 being allowed in the key expression.  That has been fixed.</p>

 <p>(SBCL only) Fixed a bug, for ACL2 hosted on SBCL, that was preventing
 inlining of functions whose name ends in @('"$INLINE"'), such as those
 generated by @(tsee defun-inline).  Thanks to Grant Jurgensen for reporting
 this bug with a helpful example.</p>

 <p>A @(tsee defabsstobj) event contains <i>function specs</i> that are each
 either a symbol or a list of the form @('(fn :kwd1 val1 ... :kwdn valn)').
 Each @('vali') must be a symbol, but when this was not the case, a raw Lisp
 error could occur.  Now a clean error message is printed, and this requirement
 on the @('vali') has been made explicit in the documentation for @(tsee
 defabsstobj).</p>

 <p>ACL2 rejected some valid @(':type') fields in defstobj forms.  This has
 been fixed; see @(see defstobj), where the &ldquo;Remark on
 @('SATISFIES')&rdquo; has been extended to describe the requisite @(see guard)
 verification.  Thanks to J. David Taylor for reporting this issue (as Issue
 1852 in the ACL2 GitHub repository) and including the following examples that
 ACL2 rejected (but now accepts).

 @({
 (defstobj st
   (a :type (complex rational)
      :initially #c(0 1)))

 (defstobj st (a :type (string 1)
                 :initially "a"))
 })

 The following additional example from Issue 1852 is still rejected, because
 @(tsee evenp) has a non-trivial @(see guard); its argument must be an
 integer.

 @({
 (defstobj st (a :type (satisfies evenp)
                 :initially 0))
 })

 However, the following variant produces a term, @('(and (integerp x) (evenp
 x))'), that is trivially guard-verifiable, so it is accepted by ACL2 (but was
 not accepted before the bug fix).

 @({
 (defstobj st (a :type (and integer (satisfies evenp))
                 :initially 0))
 })</p>

 <p>Fixed a bug that was causing errors for @(see stobj)s introduced with
 @(tsee defstobj) keyword argument @(':non-executable t') in the presence of
 large arrays.  This should not have caused an error, since that keyword
 argument prevents attempts at contructing the stobj (with its arrays).</p>

 <p>Fixed a bug in @(':')@(tsee pr) to work on function symbols introduced by
 @(tsee defstobj) (GitHub Issue 1851).  Thanks to David Taylor for reporting
 this bug.</p>

 <p>Fixed a @(see proof-builder) bug that could occasionally cause two goals to
 exist with the same name.</p>

 <p>The @(':native') option of @(tsee trace!) and @(tsee trace$) did not work
 as one would reasonably expect when SBCL is the host Lisp; now it does.</p>

 <p>Some ill-formed hard errors, for example from calls of @(tsee er), caused
 raw Lisp errors.  This has been fixed.  Thanks to Eric Smith for reporting
 this bug with an example.</p>

 <p>@('DO') @(tsee Loop$) expressions (see @(see do-loop$)) are now allowed
 that have no @('WITH') clauses.  Formerly, an expression @('(loop$ do ...)')
 caused an error with a rather nonsensical message.</p>

 <p>For a @('DO') @(tsee loop$) expression returning a @(see stobj) that
 participates in its measure, it was possible to get an inappropriate runtime
 measure error.  (An example appears in a comment in the definition of @(tsee
 do$) in the ACL2 sources.)  This bug has been fixed by modifying the
 definition of @(tsee do$) to respect singled-threadedness.</p>

 <p>A @('DO') @(tsee loop$) expression returning a @(see stobj) could cause a
 confusing error; see ACL2 source function @('chk-for-live-stobj') for an
 example.  This bug has been fixed so that no error occurs.</p>

 <p>ACL2 did an incomplete job of excluding certain forms from being evaluated
 in the top-level loop, including calls of @(tsee swap-stobjs), parallelism
 primitives (@(tsee pand), @(tsee por), @(tsee pargs), and @(tsee plet)) when
 parallel evaluation is enabled (ACL2(p) only), and @(tsee return-last) calls.
 For example, no error was signalled by the following, even though the two
 stobjs were not swapped (as shown below).

 @({
 (defstobj st1 (fld1))
 (defstobj st2 (fld2) :congruent-to st1)
 (update-fld1 1 st1)
 (update-fld2 2 st2)
 (assert-event (and (equal (fld1 st1) 1) (equal (fld2 st2) 2)))
 ; The following is equivalent to (swap-stobjs st1 st2), and it
 ; now causes an error but it did not cause an error in Version 8.6:
 (mv-let (st1 st2) (swap-stobjs st1 st2) (mv st1 st2))
 ; The following succeeds, showing that st1 and st2 were not actually swapped:
 (assert-event (and (equal (fld1 st1) 1) (equal (fld2 st2) 2)))
 })

 This bug has been fixed.</p>

 <p>@(csee Stobj) creators are once again disallowed in execution contexts (but
 are still allowed in theorems).  This requirement was relaxed (perhaps
 inadvertently) in Version  8.5.  The following example shows a problem with
 relaxing that restriction, as these events are accepted in Versions  8.5 and
 8.6, but no longer.</p>

 @({
 (defstobj st fld)
 ; Admitted in Versions 8.5 and 8.6, but no longer:
 (defun foo () (declare (xargs :guard t)) (create-st))
 (update-fld 3 st)
 (assert-event (equal (fld st) 3))
 ; Should not change global value of st:
 (foo)
 ; But (fld st) has indeed changed:
 (assert-event (equal (fld st) nil))
 })

 <p>We fixed a low-level bug in @(tsee include-book), which we have only
 observed using ACL2 built on host Lisp SBCL with safety 3 (an optimization
 setting that causes more runtime checks at the cost of longer run times).
 (Technical note: The bug was in bogus type declarations in the definition of
 ACL2 source macro @('with-hcomp-bindings').)  Thanks to Jim White for
 reporting the bug.</p>

 <h3>Changes at the System Level</h3>

 <p>Modifications have been made that allow ACL2 to be hosted on GCL Version
 2.7.0 and presumably later @(see GCL) versions; previously only GCL versions
 before 2.7.0 could host ACL2.  Essentially the only user-visible change (other
 than error prevention) is the introduction of @(tsee list$), a macro
 equivalent to @(tsee list) that can be used without a GCL 2.7.0 restriction on
 the number of arguments.  The most sweeping implementation-level change is the
 replacement of an array in support of so-called <i>static honses</i>, the
 <i>sbits array</i>, by a structure that avoids a reduced bound on array
 dimensions imposed by GCL 2.7.0.  Details may be found in a Lisp comment in
 the form @('(defxdoc note-8-7 ...)') in @(see community-books) file
 @('books/system/doc/acl2-doc.lisp').  Thanks to Camm Maguire for his help with
 this project, including (but by no means limited to) his contribution of a new
 sbits implementation.</p>

 <p>The ACL2-only manual is no longer advertised on the ACL2 home page.  The
 ACL2+Books manual is favored both because it does not have the broken links
 found in the ACL2-only manual and because the ACL2+Books manual is helpful for
 informing new users about the libraries provided by the @(see
 community-books).  Thanks to Eric Smith for encouraging this change.  Note
 that the ACL2-only manual may continue to be built in directory
 @('doc/manual/') when certifying
 @('books/system/doc/acl2-manual.lisp').  (Directory @('doc/manual/') is not to
 be confused with @('books/doc/manual/'), where the ACL2+Books manual is
 built.)</p>

 <p>For the built-in @(':')@(tsee DOC) command at the terminal: changed the top
 topic of that &ldquo;acl2-only&rdquo; manual from @('ACL2') to @('TOP').  The
 structures of the documentation trees for that version of the manual and the
 usual ACL2+Books manual are now consistent.  Thanks to Eric Smith for
 suggesting that those two manual structures be consistent.</p>

 <p>Replaced information about mailing lists in the @(see installation)
 instructions using a link to a corresponding, new documentation topic, @(see
 mailing-lists).  So now, the community can make suitable updates to that page.
 Thanks to Eric Smith for suggesting this change.</p>

 <p>The installation instructions have been moved into the manual; see @(see
 installation).  Thanks to Eric Smith for suggesting this change, which will
 allow the ACL2 community (specifically, the acl2-books community) to improve
 those instructions.</p>

 <p>By default, the directory where an ACL2 executable is to be built must not
 have a pathname that contains spaces, as before.  However, now there is a
 `@('make')' variable, @('ACL2_ALLOW_SPACES_IN_DIRECTORIES'), that may be set
 to a non-empty value in order to build an ACL2 executable in such a directory,
 as noted in the error message.  That message points out that there may be
 errors, however, when certifying books.  Thanks to Eric Smith for a discussion
 leading to this change.</p>

 <p>References to the old &ldquo;bleeding edge&rdquo; manual
 (<a
 href='https://www.cs.utexas.edu/users/moore/acl2/manuals/latest/'>https://www.cs.utexas.edu/users/moore/acl2/manuals/latest/'</a>)
 have been replaced by references to the new one
 (<a href='https://acl2.org/doc/'>https://acl2.org/doc/</a>).</p>

 <p>The documentation for @(tsee do-loop$) has been extended to illustrate how
 to signal a soft error from within the body of a @('DO') @(tsee loop$)
 expression.</p>

 <h3>EMACS Support</h3>

 <h3>Experimental Versions</h3>

 ")
other
(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.
 })")
other
(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)")
other
(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>")
other
(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)")
other
(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)")
other
(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)")
other
(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>")
other
(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)
 })")
other
(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>")
other
(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>")
*xdoc-long-numbers-introduction*constant
(defconst *xdoc-long-numbers-introduction*
  "<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)))
 })")
other
(defxdoc |Numbers in ACL2|
  :parents (|Pages Written Especially for the Tours|)
  :short "Numbers in ACL2"
  :long *xdoc-long-numbers-introduction*)
other
(defxdoc numbers-introduction
  :parents (numbers)
  :short "Numbers in ACL2"
  :long *xdoc-long-numbers-introduction*)
other
(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)")
other
(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)")
other
(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)")
other
(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>")
other
(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)")
other
(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)")
other
(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<)")
other
(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>")
other
(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>")
other
(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>")
other
(defxdoc obdd
  :parents (bdd)
  :short "Ordered binary decision diagrams with rewriting"
  :long "<p>See @(see bdd) for information on this topic.</p>")
other
(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>")
other
(defxdoc obtaining-common-lisp
  :parents (installation)
  :short "Obtaining Common Lisp"
  :long "<p>A requirement for installing ACL2 is to install a suitable
 Common Lisp implementation.  ACL2 can be hosted by several Common Lisp
 implementations, as listed alphabetically below.  The most commonly-used of
 these are SBCL and CCL, which can be obtained without charge.</p>

 <p>Regardless of which Common Lisp you choose, it is highly recommended that
 you install a 64-bit implementation.  While 32-bit Lisps are supported by the
 core ACL2 system, using a 32-bit Lisp may result in reduced performance as
 well as certification failures for certain @(see community-books).  If you are
 unsure whether your installed Common Lisp is 64-bit or not, try running the
 following:</p>

  @({
  ;; If you are in an ACL2 REPL, first do :q to exit to Common Lisp.
  ;; Evaluates to t if in a 64-bit Lisp.
  (>= most-positive-fixnum (1- (expt 2 60)))
  })

 <h3>Allegro Common Lisp</h3>

 <p><a href='https://franz.com/'>Allegro Common Lisp</a> is a commercial
 implementation.  It has been maintained for many years, but it generally runs
 ACL2 more slowly than most other implementations, and there are other issues;
 see @(see allegro-cl).</p>

 <h3>Clozure Common Lisp (CCL)</h3>

 <p><a href='https://ccl.clozure.com/'>CCL</a> is available without charge.
 See @(see ccl-installation) for instructions on how to fetch and install
 CCL.</p>

 <p>Quoting the <a href='https://ccl.clozure.com/'>CCL website</a>:

 <blockquote>

 Clozure CL (often called CCL for short) is a free Common Lisp implementation
 with a long history. Some distinguishing features of the implementation
 include fast compilation speed, native threads, a precise, generational,
 compacting garbage collector, and a convenient foreign-function interface.

 </blockquote></p>

 <p>As of this writing (July 2025), CCL does not run natively on Arm-based
 Macs.  There is an effort in progress to remedy that.</p>

 <h3>CMU Common Lisp (CMUCL)</h3>

 <p><a href='https://cmucl.org'>CMUCL</a> is available without charge.</p>

 <p>Follow the <a href='https://cmucl.org/download.html'>Download</a> link on
 <a href='https://cmucl.org'>the CMUCL website</a> to obtain CMUCL.  It has
 been maintained for many years, but it generally runs ACL2 more slowly than
 most other implementations.  At the time of writing (July, 2025), CMUCL does
 not offer a 64-bit version.</p>

 <h3>GNU Common Lisp (GCL)</h3>

 <p><a href='https://www.gnu.org/software/gcl/'>GCL</a> is available without
 charge.</p>

 <p>You can <a href='https://tracker.debian.org/pkg/acl2'>download a binary
 Debian package for ACL2</a>.  Thanks to Camm Maguire for maintaining this
 package.  Note however that it may take some time after each ACL2 release for
 this package to be updated for that release.</p>

 <p>Otherwise, it should be easy to obtain and build GCL yourself.  Note that
 ACL2 requires ANSI GCL version 2.6.12 or later.  See <a
 href='https://www.gnu.org/software/gcl/'>@('https://www.gnu.org/software/gcl/')</a>
 for instructions.  If you encounter difficulties, see @(see gcl) and perhaps
 consider the following instructions for obtaining an older version and then
 building the executable @('gcl/gcl/bin/gcl').</p>

 @({
 git clone git://git.sv.gnu.org/gcl.git
 cd gcl/gcl
 git checkout Version_2_6_13pre
 ./configure --enable-ansi && make
 })

 <h3>LispWorks</h3>

 <p><a href='https://www.lispworks.com/'>LispWorks</a> is a commercial
 implementation.  You may ask the vendor for an evaluation license for the full
 product if you are considering purchasing a license.</p>

 <h3>Steel Bank Common Lisp (SBCL)</h3>

 <p><a href='https://sbcl.org/'>SBCL</a> is available without charge.  See
 @(see sbcl-installation-brief) for instructions on how to fetch and install
 SBCL.  <b>Important</b>: For maximum performance, build from source using the
 options indicated in @(see sbcl-installation) when building with
 @('make.sh').</p>")
other
(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)")
other
(defxdoc odds
  :parents (lists acl2-built-ins)
  :short "The odd-indexed members of a list"
  :long "<p>The call @('(odds x)') returns the restriction of the true-list
 @('x') to its odd-indexed members (with zero-based indexing).  Note that if
 @('x') is a list @('(k1 a1 k2 a2 ... kn an)') that satisfies the predicate
 @(tsee keyword-value-listp), then @('(odds x)') lists the values @('ai') of
 @('x').</p>

 @(def odds)")
other
(defxdoc ok-if
  :parents (break-rewrite)
  :short "Conditional exit from @('break-rewrite')"
  :long "<p>Recall that one way to exit from a @(see break-rewrite) interactive
  break is to type the command @(':ok').  See @(see brr-commands).  The
  @(':ok') command exits silently, without printing the result of attempting to
  apply the rule that caused the break.  The @(':ok-if') command takes a term
  as an argument and is like @(':ok') but exits only if the term evaluates to
  non-@('nil').</p>

  @({
  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>")
other
(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>")
other
(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)
 })")
other
(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>

 <p>@('Open-trace-file') does not work as would reasonably be expected during
 @(tsee make-event) expansion.  Use @(tsee open-trace-file!) instead within
 @('make-event').</p>")
other
(defxdoc operational-semantics
  :parents (documentation acl2 about-acl2)
  :short "Modeling State Machines"
  :long "<p>&ldquo;<i>The meaning of a program is defined by its effect on the
  state vector</i>&rdquo; &mdash; John McCarthy, Towards a Mathematical Science
  of Computation (1962).</p>

  <p>Users of ACL2 (see @(see bib::kmm00a) and @(see bib::kmm00b)) and its
  predecessor, Nqthm (see @(see bib::bm97)), have long modeled state machines
  and verified interesting properties of programs running on those machines.
  The basic idea is to represent the state of the machine (including its
  programs) by an ACL2 object and then define an interpreter that computes a
  &ldquo;final&rdquo; state from an initial state.  In this documentation topic
  we fill out that sketch of the methodology without being specific about any
  particular machine.  We then dive into details in subsidiary topics.</p>

  <h3>Request for Suggestions from ACL2 Users</h3>

  <p>If you have ideas for additions or other improvements to the documentation
  of the ACL2 approach to operational semantics, please add suitable
  documentation or simply send your comments to the ACL2 developers.  Note that
  we have intentionally limited our literature survey to models and proof
  methods in ACL2 and Nqthm.  Widening the focus to operational semantics in
  general is simply beyond the scope of this documentation topic.  But if you
  see omissions or errors in our discussion of ACL2 or Nqthm models and proof
  methods, please either fix them or bring them to our attention, making your
  suggestions as detailed as possible, e.g., what documentation topic are you
  looking at and precisely how would you change it?  If your change involves
  citing a paper or Nqthm or ACL2 file that we have left out, please include
  the appropriate bibliographic information as well as a URL to the paper or
  file if possible.  The following documentation topics are of concern:</p>

  <h3>Recommended Order of Topics</h3>

  <ul>

  <li>operational-semantics (the current topic)</li>

  <li>@(see operational-semantics-1__simple-example)</li>

  <li>@(see operational-semantics-2__other-examples)</li>

  <li>@(see operational-semantics-3__annotated-bibliography)</li>

  <li>@(see operational-semantics-4__how-to-find-things)</li>

  <li>@(see operational-semantics-5__history-etc)</li>

  </ul>

  <h3>Prerequisites</h3>

  <p>You won't be able to prove theorems about ACL2 functions interpreting
  another language unless you can prove theorems about ACL2 functions.  An
  excellent way to test yourself is to think of a program you'd like to verify
  in that other programming language.  Code a function in ACL2 that computes
  the same answer using the same algorithm, as nearly as possible in an
  applicative setting.  So for example, if your program destructively modifies
  an array in that other programming language, perhaps model the array in ACL2
  as a list but access elements with @(tsee nth) and &ldquo;modify&rdquo;
  elements with @(tsee update-nth).  Then prove that the ACL2 function is
  correct with ACL2.  If you can do that, you're ready to try to embed that
  other language (or some fragment of it) in ACL2 and reason about such
  programs with ACL2.</p>

  <h3>Generic Description of the Methodology</h3>

  <h4>How Machines Are Modeled</h4>

  <p>In the approach ACL2 users most often take to model state machines the
  first step is to represent the relevant parts of the machine's state as an
  ACL2 object.  Then the user defines a single-step (or &ldquo;small
  step&rdquo;) function to compute the next state from the current one (and
  possibly some inputs).  Finally, the user defines a recursive function that
  iterates the single-step transition from a given initial state a given number
  of times or until some halting condition is detected in the state.  That
  function is often called the &ldquo;run&rdquo; function and is our
  operational semantic model.  See @(see
  operational-semantics-1__simple-example) for a model of an extremely simple
  machine, the way we configure ACL2 to prove things about it, some example
  proofs and other uses of the model.</p>

  <p>The argument that controls the maximum number of steps taken is often
  called a &ldquo;clock&rdquo; but it has nothing to do with the passage of
  time.  In some models the clock is just a natural number.  In others it may
  be a finite list of inputs to be successively transferred into the state on
  each cycle.  In any case, the clock guarantees that the run function
  terminates, which is a prerequisite for functions defined recursively in
  ACL2.  But do not be fooled into thinking that all programs running on the
  machine always terminate.  By appropriate use of quantification one can often
  prove that a given program never terminates or only terminates under certain
  pre-conditions.  This is discussed further in @(see
  operational-semantics-1__simple-example).</p>

  <h4>Uses of Such a Model</h4>

  <p>Such a model can be used as a prototype for the machine: the model can be
  executed on concrete states for testing purposes.  But because ACL2 is a
  formal system, it is also possible to do symbolic simulation of the model and
  to prove theorems involving the model.  Such theorems might be loosely
  classified as being &ldquo;about&rdquo; a particular program running on the
  machine or &ldquo;about&rdquo; the machine itself.  An example of the first
  might be that a certain program for the machine computes the factorial
  function.  An example of the second might be that when the machine is run
  @('(+ i j)') steps from state @('s0') the result is the same as running it
  @('i') steps from state @('s0') to get some state, @('si'), and then running
  it @('j') steps from @('si').  Such theorems are sometimes called
  &ldquo;sequential execution&rdquo; or &ldquo;semi-colon&rdquo; theorems
  because they allow a long run to be broken up into a composition of shorter
  runs.  One can even prove theorems relating one such model to another.  But
  from the logical perspective there is no practical distinction between these
  &ldquo;kinds&rdquo; of theorems: they are just ordinary theorems about ACL2
  functions.</p>

  <h4>Proving Theorems about A Model</h4>

  <p>To facilitate such proofs it is common to develop a book of rewrite (and
  other kinds of) rules that do such things as normalize compositions of
  functions used in the construction of states and clock expressions.  The
  basic idea is to control the expansions of the step and run functions to
  contain case explosions that would otherwise occur.  E.g., we usually
  configure the ACL2 database so that</p>

  <ul>

  <li>the step function only expands on a state when it is possible to
  determine what the &ldquo;next instruction&rdquo; is, rather than considering
  all possible cases,</li>

  <li>when the clock is constant (or, more precisely, when it is possible to
  determine the explicit number of steps the clock will allow) the run function
  is eliminated by expanding it to a composition of steps, and</li>

  <li>when the clock is given by a composition of functions, as in
  (+ 4 (loop-clk x y z)), a sequential composition rule is used to
  break it into a composition of runs.</li>

  </ul>

  <p>Such a configuration of ACL2 generally makes it possible to prove certain
  styles of theorems by following a well-understood methodology.</p>

  <p>For example, to express a conjecture about the final state produced by a
  program on the machine, one might write an implication whose hypothesis
  characterizes an acceptable initial state and whose conclusion is an equality
  whose left-hand side is a call of run on that state and a clock expression
  that measures exactly how many steps it will take to reach the halt state or
  return, and whose right-hand side is the symbolic expression of the correct
  final state.  The two states just mentioned and the clock expression are
  usually terms involving variables denoting values found in relevant locations
  in the initial state.  A very strong total correctness theorem for a
  factorial program might be something like &ldquo;if a natural number, @('n'),
  is found in the memory location used for the program's input, and the state
  is run @('(clk n)') steps, then the halt flag is set in the resulting state,
  and @('(fact n)'), aka, <i>n!</i>, is found in the memory location used for
  the program's return value &mdash; and the program counter is set to the
  correct next instruction and no other part of the state has changed.&rdquo;
  Alternatively, the theorem might only express some post-condition of the
  final state.  The examples in @(see operational-semantics-1__simple-example)
  will make this clearer.  The methodology for proving such theorems is
  demonstrated there too.</p>

  <p>The clock term, @('(clk n)') above, is a constructive expression of an
  existential quantifier meaning &ldquo;there exists a clock that drives the
  machine from the given initial state to the given final state.&rdquo; It is
  also sometimes possible to prove that no such clock exists.  There are tools
  that can, for simple programs, generate appropriate clock terms.  Of course,
  the problem is undecidable.</p>

  <p>Proofs of such theorems are most often done by induction, appealing to
  similar lemmas about the effects of loops and subroutine calls.  But proofs
  using inductive assertions and other mathematical techniques can be used.</p>

  <p>The methodology described above generally limits the human to creative
  contributions (like identifying invariants being maintained) and relegates to
  ACL2 the tedious unwinding of possibly long chains of symbolic computation.
  The previously mentioned documentation topic, @(see
  operational-semantics-1__simple-example), carries out this entire program for
  a simple machine, explicates the methodology, and uses it to prove a variety
  of theorems.</p>

  <p>Following this approach, users of Nqthm and ACL2 have modeled and verified
  properties of many interesting machines.  More precise references to the work
  mentioned below as well as models and proofs about other machines &mdash; and
  other kinds of properties, like absence of deadlock &mdash; may be found in
  @(see operational-semantics-2__other-examples).</p>

  <h4>Advice</h4>

  <p>After you are familiar with how to use ACL2 and have studied some of the
  models described here, you are ready to try to develop your own models. We
  offer three pieces of advice.</p>

  <ul>

  <li>Start small, e.g., model half a dozen routine instructions and master the
  methodology so that you can &ldquo;automatically&rdquo; prove things about
  simple programs.  Be sure that your proofs don't rely on the small size of
  the model; in particular, don't repeatedly enumerate all possible
  instructions.  Then add one new feature to the model and elaborate the
  methodology.  You will often find there are multiple ways to represent the
  state and state changes.  By starting small you will be able to iterate more
  quickly to find the best way to formalize new features and cope with the
  resulting complexity.</li>

  <li>Consider the necessity of introducing multiple layers of abstraction.
  For example your most realistic model might have finite bounds on all
  resources, but it might be worth your while to &ldquo;duplicate&rdquo; the
  model with unbounded resources but with meters that record the maximal extent
  of the resources used.  Then prove a theorem relating the two models.</li>

  <li>As usual with ACL2, think carefully about how the prover will use the
  lemmas you prove.  They are not just expressing mathematical relations but are
  used operationally to transform the formulas being proved.</li>

  </ul>

  <h3>Overview of the Remaining Topics on Operational Semantics</h3>

  <p>Our discussion of the details of operational semantics in ACL2 is
  structured as follows.</p>

  <ul>

  <li> @(see operational-semantics-1__simple-example) &mdash; carries out
  the generic methodology to formalize and prove theorems about a very simple
  machine, called M1.  M1 is a toy Java Virtual Machine (JVM) supporting just
  stack-based arithmetic and branch instructions.  We highly recommend this
  section, though users already familiar with this style of model may wish just
  to skim it.</li>

  <li>@(see operational-semantics-2__other-examples) &mdash; briefly
  summarizes some other examples of operational models with citations to the
  relevant source documents.  The topic has several goals.  One is to show how
  we can handle programming features omitted from M1, e.g., subroutine call and
  return, data types, threads, monitors, etc.  A second goal is to demonstrate
  that the methodology allows really large complex models, like of the JVM or
  the x86, that can be executed in ACL2 to emulate the machine in question and
  as the basis of formal proofs about the machine.  A third goal is to point
  out alternative ACL2 proof styles and tools that may be of use while trying
  to prove theorems about state machines.</li>

  <li>@(see operational-semantics-3__annotated-bibliography) &mdash; is just
  what it says: an annotated bibliography.  The annotations you see in this
  bibliography are akin simply to keywords.  But if you select a given citation
  you'll generally see a discussion of how the work fits into the scheme of
  things.  This section is an alternative way to browse through Nqthm and ACL2
  examples of state machines, proofs, proof styles, and tools.</li>

  <li> @(see operational-semantics-4__how-to-find-things) &mdash; the various
  topics on operational semantics cite papers and files that are not part of
  the ACL2 documentation; for example, in these topics you might see utterances
  such as &ldquo;Nqthm source file @('prove.lisp')&rdquo;, &ldquo;ACL2 source
  file @('rewrite.lisp')&rdquo;, &ldquo;Nqthm proof script
  @('examples/hunt/fm8501.lisp')&rdquo; and &ldquo;ACL2 directory
  @('books/models/jvm/m1/')&rdquo;; this brief topic explains how to
  dereference these utterances.  </li>

  <li> @(see operational-semantics-5__history-etc) &mdash; a discussion of
  early work in the 1970s and 1980s by members of the Boyer-Moore
  community to model state machines, and how that work influenced the evolution
  of Nqthm and ACL2.</li>

  </ul>

  ")
other
(defxdoc operational-semantics-1__simple-example
  :parents (operational-semantics)
  :short "M1: definition, rules, clocks, proofs"
  :long "<h3>Organization of This Topic</h3>

  <p>As a hypertext document, this topic is &ldquo;flat,&rdquo; not structured
  as a tree of subtopics.  We implemented it this way to make it easier to
  search.</p>

  <ul>
  <li>Introduction</li>
  <li>Setting up a Symbol Package</li>
  <li>The Definition of M1</li>
  <li>Programming M1</li>
  <li>&ldquo;Teaching&rdquo; the Prover How to Control M1</li>
  <ul>
  <li>Arithmetic</li>
  <li>Resolving &ldquo;Reads&rdquo; and &ldquo;Writes&rdquo;</li>
  <li>Keeping &ldquo;Abstractions&rdquo; Abstract</li>
  <li>Controlling Case Explosion due to Step</li>
  <li>Clock Expressions</li>
  <li>Expanding @('m1')</li>
  </ul>
  <li>Playing with Program *pi*: Execution, Symbolic Execution, and Proof of
  Correctness</li>
  <ul>
  <li>The Clock for Factorial</li>
  <li>Computing with M1</li>
  <li>Symbolic Execution of M1 Code</li>
  <li>Proving Theorems about M1 Programs</li>
  <ul>
  <li>Step 0: The Specification</li>
  <li>Step 1: The Semantic Function</li>
  <li>Step 2: Relate the Semantic Function to the Code</li>
  <li>Step 3: Relate the Semantic Function to the Specification</li>
  <li>Step 4: Total Correctness</li>
  </ul>
  </ul>
  <li>More M1 Programs and Proofs</li>
  <li>More Elaborate Models of the JVM: From M1 to M6</li>
  </ul>

  <h3>Introduction</h3>

  <p>In this topic we explain, by example, the most common way to formalize a
  computing machine in ACL2 and then reason about it. The machine we have in
  mind will be called &ldquo;M1&rdquo; and is a &ldquo;toy&rdquo; version of
  the Java Virtual Machine or &ldquo;JVM.&rdquo; More precisely, it is a simple
  stack machine having a fixed number of registers, hereafter called
  &ldquo;local variables,&rdquo; and an execute-only program memory.  There
  will only be eight instructions.  We will then write and verify a factorial
  program for it and mention many more M1 programs that have been verified
  &mdash; and which we urge you to solve as practice problems.  Despite its
  simplicity, M1 is equivalent to a Turing machine and, in fact, that fact is
  among the theorems proved about M1.  Full references are given when we survey
  the M1 results available.</p>

  <p>(Historical Aside: What we're calling M1 was called
  &ldquo;Small-Machine&rdquo; in Nqthm.  See @(see bib::bm96) and the
  methodology described here was essentially fully developed before ACL2, Java,
  or the JVM came along.)</p>

  <p>M1 does not support bytecode verification, method invocation (procedure
  call) and return, data objects other than ACL2's unbounded numbers, threads,
  exceptions, and many other features of modern machines and languages.
  However, M1 is an excellent place to start when learning how to formalize a
  machine and to prove theorems about it.  Furthermore, it is the starting
  place of a series of machine models in the JVM family that we explore more
  fully at the end of this documentation topic.</p>

  <p>Our discussion of this simple machine is quite long!  The reason is that
  we're not trying just to explain the M1 model and how to prove correctness
  theorems about M1 programs; we're trying to explain how to create your own
  model, how to configure ACL2 to manipulate it, and how to phrase correctness
  conjectures so that ACL2 can prove them.  We're using a simple machine as
  the vehicle.</p>

  <p>The ACL2 book defining M1 and all the necessary configuration lemmas,
  @('models/jvm/m1/m1.lisp'), is less than 8K bytes, and the script for proving
  an M1 factorial program correct, @('models/jvm/m1/fact.lisp'), is less than
  6K bytes.  If we strip out the comments, those two files combined are less
  than 8K bytes or about 5 pages.  But this doc topic is about 64K bytes or
  about 35 pages.  So don't despair.  It takes longer to explain how to do it
  than to do it!</p>

  <p>You can find the definition of M1 and all of the work done with it on the
  ACL2 directory @('books/models/jvm/m1').  It might be easiest to fire up
  your ACL2 system and do this.</p>

  @({
  (include-book "models/jvm/m1/m1" :dir :system)
  (in-package "M1")
  })

  <p>Then, to see the definition of any symbol mentioned below you could just
  issue the @(':')@(tsee pe) command.  For example, to see the definition of
  the function @('execute-ILOAD'), aka @('execute-iload'), you could type
  @(':pe execute-iload') to the interactive prompt in your ACL2 session.  This
  doc topic will not exhibit all the functions but will give examples of each
  &ldquo;kind&rdquo; of function involved in M1.</p>

  <h3>Setting up a Symbol Package</h3>

  <p>All of the functions defined to describe M1 are in a new symbol package
  named @('"M1"').  This allows us to avoid name clashes with functions like
  @('pop'), @('program'), and @('pc') that are predefined in the default
  @('"ACL2"') symbol package.</p>

  @({
  (defpkg "M1"
    (set-difference-eq
      (union-eq *acl2-exports*
                *common-lisp-symbols-from-main-lisp-package*)
      '(push pop pc program step nth update-nth nth-update-nth)))
  })

  <p>Note that we put all the usual ACL2 symbols and Common Lisp symbols in the
  new package, except for a few whose names clash with names we want to define
  for use in our model.</p>

  <p>See the ACL2 file @('books/models/jvm/m1/m1.acl2').</p>

  <h3>The Definition of M1</h3>

  <p>See the ACL2 file @('books/models/jvm/m1/m1.lisp') for all of the functions mentioned
  below.</p>

  <p>The <i>state</i>, @('s'), of M1 will be given by a list of four elements, accessed with
  the functions named below.</p>

  <ul>
  <li>@('pc') &mdash; a natural number giving the position in @('(program s)') of the
   next instruction</li>

  <li>@('locals') &mdash; a list containing the values, by position, of the
  local variables of the program</li>

  <li>@('stack') &mdash; a list representing a stack of intermediate results,
  the @('car') being the topmost value </li>

  <li>@('program') &mdash; a list of instructions (see below)</li>

  </ul>

  <p>States will be constructed with</p>

  @({
  (defun make-state (pc locals stack program)
     (cons pc
           (cons locals
                 (cons stack
                       (cons program
                             nil)))))
  })

  <p>Thus, @('(make-state pc locals stack program)') is just @('(list pc locals
  stack program)').  The state accessors just select the appropriate elements
  of a state, e.g., @('(stack (make-state pc locals stack program))') is just
  @('stack').</p>

  <p>To &ldquo;abstractly&rdquo; treat a list as a stack we define</p>

  @({
 (defun push (x y) (cons x y))   ; return a new stack with x on top of stack y
 (defun top (stack) (car stack)) ; return topmost element of stack
 (defun pop (stack) (cdr stack)) ; remove topmost element and return that stack
  })

  <p>To access and update the elements of a list by 0-based positions we define</p>

  @({
 (defun nth (n list)
   (if (zp n)
       (car list)
     (nth (- n 1) (cdr list))))

 (defun update-nth (n v list)
   (if (zp n)
       (cons v (cdr list))
     (cons (car list)
           (update-nth (- n 1) v (cdr list)))))
  })

  <p>Thus, @('(nth 3 '(10 20 30 40 50))') is @('40') and @('(update-nth 3 45
  '(10 20 30 40 50))') is @('(10 20 30 45 50)').</p>

  <p>The eight M1 instructions are</p>
  <ul>

  <li>@('(ICONST i)') &mdash; push @('i') onto the stack and advance the pc by
      1</li>

  <li>@('(ILOAD i)') &mdash; push the value of the @('i')th local onto the
      stack and advance the pc by 1</li>

  <li>@('(ISTORE i)') &mdash; pop the topmost value from the stack, store it as
      the value of the @('i')th local, and advance the pc by 1</li>

  <li>@('(IADD)') &mdash; pop the topmost value, @('u'), and value just under
       it, @('v'), from the stack, push @('(+ v u)') onto the stack, and
       advance the pc by 1</li>

  <li>@('(ISUB)') &mdash; pop the topmost value, @('u'), and value just under
       it, @('v'), from the stack, push @('(- v u)') onto the stack, and
       advance the pc by 1</li>

  <li>@('(IMUL)') &mdash; pop the topmost value, @('u'), and value just under
      it, @('v'), from the stack, push @('(* v u)') onto the stack, and
      advance the pc by 1</li>

  <li>@('(GOTO i)') &mdash; advance the pc by @('i')</li>

  <li>@('(IFEQ i)') &mdash; pop the topmost value from the stack and if it is
      0, then advance the pc by @('i') and otherwise advance the pc by 1</li>

  </ul>

  <p>In the case of both @('GOTO') and @('IFEQ'), the pc may be
  &ldquo;advanced&rdquo; by a negative amount.</p>

  <p>To access the components of an instruction we define</p>

  @({
  (defun op-code (inst) (nth 0 inst))  ; return the op-code of instruction inst
  (defun arg1 (inst) (nth 1 inst))     ; return the operand of instruction inst
  })

  <p>For each instruction we define the function that takes the instruction and a state and
  returns the next state.  For example,</p>

  @({
  (defun execute-ICONST (inst s)
    (make-state (+ 1 (pc s))
                (locals s)
                (push (arg1 inst) (stack s))
                (program s)))

  (defun execute-ILOAD (inst s)
    (make-state (+ 1 (pc s))
                (locals s)
                (push (nth (arg1 inst)
                           (locals s))
                      (stack s))
                (program s)))

  (defun execute-ISTORE (inst s)
    (make-state (+ 1 (pc s))
                (update-nth (arg1 inst) (top (stack s)) (locals s))
                (pop (stack s))
                (program s)))

  (defun execute-IADD (inst s)
    (declare (ignore inst))
    (make-state (+ 1 (pc s))
                (locals s)
                (push (+ (top (pop (stack s)))
                         (top (stack s)))
                      (pop (pop (stack s))))
                (program s)))

  (defun execute-IFEQ (inst s)
    (make-state (if (equal (top (stack s)) 0)
                    (+ (arg1 inst) (pc s))
                  (+ 1 (pc s)))
                (locals s)
                (pop (stack s))
                (program s)))
  })

  <p>The other instructions are analogous.  Many users define an ACL2 macro,
  typically named @('modify') that takes a machine state and some keyword
  argument and builds a new state from the given one, with new values for the
  keys specified with keywords.  So for example, in that idiom one might
  replace the @('make-state') call in @('execute-IADD') by</p>

  @({
  (modify s :pc (+ 1 (pc s))
            :stack (push (+ (top (pop (stack s)))
                            (top (stack s)))
                         (pop (pop (stack s)))))
  })

  <p>omitting any mention of @('locals') and @('program') because they are not
  changed.  But for beginners we prefer the @('make-state') idiom because it is
  more explicit.</p>

  <p>We wrap all those &ldquo;execute&rdquo; functions up into a
  big-switch.</p>

  @({
  (defun do-inst (inst s)         ; do instruction inst to state s
    (if (equal (op-code inst) 'ILOAD)
        (execute-ILOAD  inst s)
        (if (equal (op-code inst) 'ICONST)
            (execute-ICONST  inst s)
            (if (equal (op-code inst) 'IADD)
                (execute-IADD   inst s)
                (if (equal (op-code inst) 'ISUB)
                    (execute-ISUB   inst s)
                    (if (equal (op-code inst) 'IMUL)
                        (execute-IMUL   inst s)
                        (if (equal (op-code inst) 'ISTORE)
                            (execute-ISTORE  inst s)
                            (if (equal (op-code inst) 'GOTO)
                                (execute-GOTO   inst s)
                                (if (equal (op-code inst) 'IFEQ)
                                    (execute-IFEQ   inst s)
                                    s)))))))))
  })

  <p>Observe that if @('do-inst') is called on an unknown instruction it returns
  the state unchanged.  Thus @('(do-inst '(HALT) s)') is just @('s').</p>

  <p>To access the next instruction in a state we define</p>

  @({
  (defun next-inst (s)
    (nth (pc s) (program s)))
  })

  <p>In some of our theorems about @('m1') it is convenient to have a way to
  say &ldquo;the machine has reached the @('(HALT)') instruction, i.e., the
  @('pc') points to @('(HALT)'),&rdquo; so we define</p>

  @({
  (defun haltedp (s)
    (equal (next-inst s) '(HALT)))
  })

  <p>To &ldquo;step&rdquo; the machine just once we define</p>

  @({
  (defun step (s)
    (do-inst (next-inst s) s))
  })

  <p>Finally we define @('m1') to step @('n') times.</p>

  @({
  (defun m1 (s n)
    (if (zp n)
        s
        (m1 (step s) (- n 1))))
  })

  <p>In a model like this one, where we control the length of the run by a
  natural-number step count, we often call the second argument of @('m1') the
  &ldquo;clock.&rdquo; One might think of it as counting &ldquo;cycles&rdquo;
  but not &ldquo;run time.&rdquo; Some authors call the argument
  &ldquo;fuel&rdquo;.  In some models the &ldquo;clock&rdquo; might actually be
  a list and be called by a different name depending on how that list is used.
  We've seen it called &ldquo;schedule&rdquo; (because it specifies which
  process is to step next), &ldquo;inputs&rdquo; (because it specifies what
  signals appear on certain pins in the each cycle), and
  &ldquo;oracle&rdquo; (because it specifies &ldquo;random&rdquo; choices).</p>

  <h3>Programming M1</h3>

  <p>Below we exhibit an M1 program for computing factorial.  For convenience
  we define a constant with this program as its value so we can refer to it.
  We name the constant &ldquo;pi&rdquo; for &ldquo;program&rdquo;.  In the
  comments to the right of the instructions we show the position (i.e., the
  corresponding pc) of the instruction and pseudocode for the nearby snippet of
  code.  In this program we will have just two local variables, called
  &ldquo;@('n')&rdquo; and &ldquo;@('ans')&rdquo; in the pseudocode, in
  positions 0 and 1 respectively of the @('locals').  We'll compute @('(fact
  n)') and leave the result in @('ans') and on top of the stack.</p>

  @({
  (defconst *pi*
                  ; pc    pseudo-code
    '((iconst 1)  ;  0                    [Block 1]
      (istore 1)  ;  1    ans := 1;

      (iload 0)   ;  2  loop:             [Block 2]
      (ifeq 10)   ;  3    if n=0 then goto exit (i.e., pc+10);

      (iload 1)   ;  4                    [Block 3]
      (iload 0)   ;  5
      (imul)      ;  6
      (istore 1)  ;  7    ans := ans * n;

      (iload 0)   ;  8                    [Block 4]
      (iconst 1)  ;  9
      (isub)      ; 10
      (istore 0)  ; 11    n := n - 1;

      (goto -10)  ; 12    goto loop;      [Block 5]

      (iload 1)   ; 13 exit:              [Block 6]
      (halt)))    ; 14   return ans;
  })

  <p>We've put blank lines in the display to break the program into blocks,
  which we've numbered.  We'll describe each block's effect now, just to drive
  home how @('m1') behaves.  We will use these blocks in some examples later.</p>

  <p>Block 1 is the &ldquo;compilation&rdquo; of &ldquo;ans := 1;&rdquo; The
  @('(iconst 1)') pushes @('1') onto the stack and the @('(istore 1)') pops it
  off into local 1, which we're calling &ldquo;@('ans')&rdquo;.</p>

  <p>We have labeled the top of Block 2 &ldquo;@('loop').&rdquo; Although it is
  not syntactically obvious in this assembly-like code, subsequent code will
  jump back to @('pc') 2.</p>

  <p>Block 2 is the compilation of &ldquo;if @('n')=0, then goto exit,&rdquo;
  where we labeled @('pc') 13 &ldquo;@('exit').&rdquo; In particular, the
  @('(iload 0)') at @('pc') 2 pushes the value of &ldquo;@('n')&rdquo;) onto
  the stack.  The instruction at @('pc') 3, @('(ifeq 10)'), pops it off and
  tests it against @('0').  If @('n')=0, the @('ifeq') increments the @('pc')
  by 10, transferring control to @('pc') 13.</p>

  <p>Block 3 is the compilation of &ldquo;ans := ans * n;&rdquo;.  Walk that
  code segment to understand.</p>

  <p>Block 4 is the compilation of &ldquo;n := n - 1;&rdquo;.</p>

  <p>Block 5 jumps back to @('pc') 2 (i.e., @('loop')).  In particular, the
  @('(goto -10)') at @('pc') 12 adds -10 to the @('pc').</p>

  <p>Block 6 is the compilation of &ldquo;return @('ans').&rdquo; It just
  pushes local 1 onto the stack and halts, leaving the @('pc') at 14.</p>

  <p>If all we wanted to do with @('m1') is run programs on it, we're done!
  @('M1') as defined above can be run on concrete input to produce concrete
  results.</p>

  <p>For example, to compute factorial of 6 we would start with this state:</p>

  @({
  (make-state 0           ; pc - first instruction
              (list 6 0)  ; locals - n = 6, ans = 0
              nil         ; stack - empty
              *pi*)       ; program
  })

  <p>and run it with @('m1').  Of course, we need to specify the
  &ldquo;clock,&rdquo; the number of steps we want to take.  In the absence of
  any better idea, we could just try 1000 and see if the final state is at
  @('pc') 14, which is the @('(HALT)').</p>

  @({
  M1 !>(m1 (make-state 0          ; pc
                       (list 6 0) ; locals
                       nil        ; stack
                       *pi*)      ; program
           1000)
  (14 (0 720)                     ; pc and locals
      (720)                       ; stack
      ((ICONST 1)                 ; program
       (ISTORE 1)
       (ILOAD 0)
       (IFEQ 10)
       (ILOAD 1)
       (ILOAD 0)
       (IMUL)
       (ISTORE 1)
       (ILOAD 0)
       (ICONST 1)
       (ISUB)
       (ISTORE 0)
       (GOTO -10)
       (ILOAD 1)
       (HALT)))
    })

  <p>Notice that the machine reached the @('(HALT)') at @('pc') 14 and @('720')
  is on top of the stack.  We also may note that local 0 has been zeroed out
  and local 1 contains 720.</p>

  <p>We will deal with the clock situation more carefully later.  It should be
  noted that our definition of @('m1') actually executes 1000 steps if that's
  what the clock says.  In particular, the @('HALT') instruction is a no-op,
  making no state change, and @('m1') just continues to bang away while sitting
  on that instruction until the clock runs out.  We could, of course, define
  @('m1') differently, so as to return @('s') whenever when @('(step s)') =
  @('s').  But we'll keep @('m1') simple.</p>

  <h3>&ldquo;Teaching&rdquo; the Prover How to Control M1</h3>

  <p>We'll now turn our attention to configuring ACL2 to prove things about M1
  programs.  This basically consists of proving lemmas to be used as
  @(':')@('rewrite') rules and, sometimes, disabling functions so that their
  calls don't expand automatically.  We'll explain the motivations of our
  configuration as we go, but true understanding of the motivation won't come
  until we prove an M1 program correct.  Be patient.</p>

  <p>This section only exhibits some of the rules we introduce.  All of the
  necessary rules can be found in the same file in which M1 is defined, the
  ACL2 file @('books/models/jvm/m1/m1.lisp').  By the way, the sequence in
  which these definitions and lemmas appear below is not identical to the
  sequence in the @('m1.lisp') file, but they're all there.  In telling the
  story we just found the sequence below a little more natural.</p>

  <h4>Arithmetic</h4>

  <p>To be able to reason about simple arithmetic, we include one of the
  standard arithmetic books.</p>

  @({
  (include-book "arithmetic-5/top" :dir :system)
  })

  <h4>Resolving &ldquo;Reads&rdquo; and &ldquo;Writes&rdquo;</h4>

  <p>The local variables are read and written positionally using @('nth') and
  @('update-nth').  It is helpful to have the following lemmas to resolve reads
  after writes and eliminate shadowed writes.  (These lemmas are not necessary
  in most of our @('m1') proofs because the locals are generally expressed as
  &ldquo;semi-concrete&rdquo; list (i.e., a @('cons') tree with symbolic
  expressions in the @('car') positions) of a fixed length, like @('(list a b
  c)') and reads and writes always address an explicitly specified position,
  like @('2'), so even after a sequence of @('m1') instructions storing values,
  the symbolic expression of the locals will be a fixed length semi-concrete
  list.  For example @('(update-nth 2 (+ u v) (list a b c d))') is
  automatically rewritten to @('(list a b (+ u v) d)') just by the definition
  of @('update-nth').  But in more general situations, where the position of
  the local variable is not an explicit constant or the symbolic expression of
  the current values of the locals in the state is not an explicit @('cons')
  tree, the lemmas below are crucial.</p>

  @({
  (defthm nth-add1!
    (implies (natp n)
             (equal (nth (+ 1 n) list)
                    (nth n (cdr list)))))

  (defthm nth-update-nth
    (implies (and (natp i) (natp j))
             (equal (nth i (update-nth j v list))
                    (if (equal i j)
                        v
                      (nth i list)))))

  (defthm update-nth-update-nth-1
    (implies (and (natp i) (natp j) (not (equal i j)))
             (equal (update-nth i v (update-nth j w list))
                    (update-nth j w (update-nth i v list))))
    :rule-classes ((:rewrite :loop-stopper ((i j update-nth)))))

  (defthm update-nth-update-nth-2
    (equal (update-nth i v (update-nth i w list))
           (update-nth i v list)))
  })

  <h4>Keeping &ldquo;Abstractions&rdquo; Abstract</h4>

  <p>To allow us to reason about &ldquo;abstract&rdquo; structures represented
  by @('cons')es, without expanding their definitions, we prove such lemmas
  as</p>

  @({
  (defthm stacks
    (and (equal (top (push x s)) x)
         (equal (pop (push x s)) s)

  ; These next two are needed because some push expressions evaluate to
  ; list constants, e.g., (push 1 (push 2 nil)) becomes '(1 2) and '(1
  ; 2) pattern-matches with (cons x s) but not with (push x s).

         (equal (top (cons x s)) x)
         (equal (pop (cons x s)) s)))
  })

  <p>We prove the analogous rules about state accessors and @('make-state'),
  e.g., @('(equal (pc (make-state pc locals stack program)) pc)').
  Then we disable all the defined functions just mentioned so they never
  expand.</p>

  <h4>Controlling Case Explosion due to Step</h4>

  <p>Next we introduce a crucial rule for controlling the expansion of
  @('step').  The term @('(step s)') can always be expanded into that
  big-switch that considers all the possible @('op-code')s.  That is generally
  a disaster.  Think of what would happen if @('(step (step s))') were
  automatically expanded when we have no information about @('s'): the inner
  @('step') would introduce a 9-way case split and the outer one would turn
  that into an 81-way case split considering all of the possibilities for the
  first two instructions.  We want to expand @('step') only when we know
  something definite about the instruction that is to be executed.  So we prove
  this logically trivial theorem.</p>

  @({
  (defthm step-opener
    (implies (consp (next-inst s))
             (equal (step s)
                    (do-inst (next-inst s) s))))
  })

  <p>The conclusion is just the definition of @('step')!  So the hypothesis is
  completely unnecessary from a logical perspective.  But operationally, if
  this rule has been proved and then @('step') is disabled, the rewriter will
  expand @('(step s)') only if @('(next-inst s)') can be proved to satisfy
  @('consp').  The most common way for @('(next-inst s)') to be a @('consp') is
  when both the @('pc') and the @('program') in state @('s') are quoted
  constants and @('program') is a well-formed program.  But we don't want to
  require exactly that because it is too restrictive.  For example, in machine
  models supporting subroutine calls, the typical correctness theorem for a
  subroutine says very little about the entire &ldquo;program space&rdquo; but deals with
  an @('invoke')- or @('jsr')-type instruction to a place where the code for
  the subroutine is found.  (If you inspect
  @('books/models/jvm/m2/examples.lisp') and look at @('example4') you will see
  such a correctness theorem.)  As models get more complex you may have to
  adjust @('step-opener') accordingly, though this simple version is
  surprisingly effective.</p>

  <p>Having established @('step-opener'), we disable @('step') so that the only
  way it ever expands is when the @('next-inst') is provably a @('consp').</p>

  @({
  (in-theory (disable step))
  })

  <p><b>Symbolic Execution Example 1</b></p>

  <p>To illustrate the rules just described, consider the symbolic expression</p>

  @({
  (step
    (step
      (make-state 0
                  (list n ans)
                  stack
                  *pi*    ; '((ICONST 1)  ;  0             [Block 1]
                          ;   (ISTORE 1)  ;  1   ans := 1;
                          ;   ...         ;  2
                          ;   ...)        ; ...
                  )))
  })

  <p>Note that the outer @('step') cannot be expanded because @('step') is disabled
  and we can't determine the @('next-instr') of the (unsimplified) inner @('step').</p>

  <p>But @('step-opener') fires on the inner @('step') because @('next-inst')
  of the above @('make-state') just rewrites to @(''(ICONST 1)') using the
  definitions of @('pc'), @('program'), and @('nth').  So the term above is
  rewritten to</p>

  @({
  (step
    (make-state 1
                (list n ans)
                (push 1 stack)
                *pi*    ; '((ICONST 1)    ;  0             [Block 1]
                        ;   (ISTORE 1)    ;  1   ans := 1;
                        ;   ...           ;  2
                        ;  ...)           ; ...
                ))
  })

  <p>using @('step-opener'), @('next-inst'), @('do-inst'), @('execute-iconst'),
  @('nth'), and @('update-nth').  @('Execute-iconst') just advanced the @('pc')
  from 0 to 1 and symbolically pushed a @('1') into the @('stack').</p>

  <p>But now @('step-opener') can fire on that outer @('step') because we see
  that the @('next-inst') of this state is @('(ISTORE 1)').  So the term rewrites
  to</p>

  @({
  (make-state 2
              (list n 1)
              stack
              *pi*    ; '((ICONST 1)      ;  0             [Block 1]
                      ;   (ISTORE 1)      ;  1   ans := 1;
                      ;   ...             ;  2
                      ;   ...)            ; ...
              )
  })

  <p>We've just symbolically executed the first two instructions of @('*pi*')
  on a symbolic state containing two unspecified locals and an unspecified
  stack.  This simplification is completely automatic.</p>

  <p><b>Symbolic Execution Example 2</b></p>

  <p>We'll show one more symbolic execution of a snippet from program
  @('*pi*').  This time, let's start at top of the loop in @('*pi*'), @('pc')
  2, and run down through the @('(GOTO -10)') where the program jumps back to
  the loop.  That takes 11 @('step')s.  Furthermore, assume that @('n') (local
  0) is a non-0 natural number and @('ans') (local 1) is a natural number.</p>

  @({
  (m1 (make-state 2 (list n ans) stack *pi*) 11)
  =
  (step
   (step
    (step
     (step
      (step
       (step
        (step
         (step
          (step
           (step
            (step
             (make-state 2
                         (list n ans)
                         stack
                         *pi*    ; '(...        ;  ...
                                 ;   (ILOAD 0)  ;  2 loop: [Block 2]
                                 ;   (IFEQ 10)  ;  3
                                 ;   (ILOAD 1)  ;  4       [Block 3]
                                 ;   (ILOAD 0)  ;  5
                                 ;   (IMUL)     ;  6
                                 ;   (ISTORE 1) ;  7
                                 ;   (ILOAD 0)  ;  8       [Block 4]
                                 ;   (ICONST 1) ;  9
                                 ;   (ISUB)     ; 10
                                 ;   (ISTORE 0) ; 11
                                 ;   (GOTO -10) ; 12       [Block 5]
                                 ;   ...)
                         ))))))))))))
  })

  <p>(Exceedingly deep nests of @('step')s can cause stack overflow in the ACL2
  rewriter.  We discuss this problem the presentation of the @('m1-opener')
  lemma below.)</p>

  <p>We won't show the step-by-step results of this symbolic execution (thank
  goodness!), but the first two instructions just move the @('pc') from 2 to 4
  because @('n') is not 0.  The next four replace @('ans') by @('(* ans n)'),
  the next four replace @('n') by @('(- n 1)'), and the last @('step') sets the
  @('pc') to the top of the loop at @('pc') 2 again.  Despite the pushing and
  popping on the stack, by the time we get back to the top of the loop, the
  stack is unchanged.  The result is</p>

  @({
  (make-state 2
              (list (- n 1) (* ans n))
              stack
              *pi*               ; '(...        ;  ...
                                 ;   (ILOAD 0)  ;  2 loop: [Block 2]
                                 ;   (IFEQ 10)  ;  3
                                 ;   (ILOAD 1)  ;  4       [Block 3]
                                 ;   (ILOAD 0)  ;  5
                                 ;   (IMUL)     ;  6
                                 ;   (ISTORE 1) ;  7
                                 ;   (ILOAD 0)  ;  8       [Block 4]
                                 ;   (ICONST 1) ;  9
                                 ;   (ISUB)     ; 10
                                 ;   (ISTORE 0) ; 11
                                 ;   (GOTO -10) ; 12       [Block 5]
                                 ;   ...)
              )
  })

  <p>We'll see this expression again later.  What's important is that with the
  @('step') rules we have in place, ACL2 will automatically do symbolic
  evaluation of concrete code sequences.</p>

  <h4>Clock Expressions</h4>

  <p>Many (most?) of our theorems about specific M1 programs will involve a
  clock expression which specifies exactly how many steps we want the machine
  to take.  It is not as hard as you might think to create functions that
  compute this &mdash; provided you can prove that the clock function
  terminates, which is of course generally undecidable but frequently trivial.
  And, proofs via clock functions are not only equivalent to proofs by
  inductive assertions but that has been proved with ACL2 and tools are
  provided to convert back and forth between the two proof styles (see @(see
  bib::rm04)).</p>

  <p>Clock functions for @('m1') are recursive functions defined that use
  arithmetic expressions to compute the lengths of code segments.  However, a
  key part of our strategy for controlling proofs is to use the structure of
  the clock function and its arithmetic expressions to decompose
  &ldquo;long&rdquo; runs of @('m1') into compositions of shorter runs.  In
  order to do that, we must prevent the prover from rearranging our clocks!
  That is, @('(m1 s (+ i j))') will decompose differently than @('(m1 s (+ j
  i))'), but the arithmetic library might rearrange the clock, e.g., by using
  the commutativity of addition.  So instead of using @('+') to express the
  addition of two clocks we define @('clk+') to be @('+'), but we'll disable
  its definition to protect clocks from arithmetic reasoning.  We will arrange
  for @('clk+') to take more than just two arguments and will reveal that it is
  associative.</p>

  @({
  (defun binary-clk+ (i j)
    (+ (nfix i) (nfix j)))

  (defthm clk+-associative
    (equal (binary-clk+ (binary-clk+ i j) k)
           (binary-clk+ i (binary-clk+ j k))))

  (defmacro clk+ (&rest args)
    (if (endp args)
        0
        (if (endp (cdr args))
            (car args)
            `(binary-clk+ ,(car args)
                           (clk+ ,@(cdr args))))))
  })

  <p>Thus @('(clk+ a b c)') is just an abbreviation for @('(binary-clk+
  a (binary-clk+ b c))'), and the prover will rewrite @('(clk+ (clk+ a b) (clk+
  d e))') to the @('binary-clk+') version of @('(clk+ a b c d)').</p>

  <p>The key fact about clocks and @('m1') is captured in the following rewrite
  rule, which is sometimes called the &ldquo;sequential execution&rdquo; rule
  or the &ldquo;semi-colon rule.&rdquo;</p>

  @({
  (defthm m1-clk+
    (equal (m1 s (clk+ i j))
           (m1 (m1 s i) j)))
  })

  <p>Having proved this, we disable @('binary-clk+') so that we have complete
  control over how long runs decompose.</p>

  <h4>Expanding @('m1')</h4>

  <p>Of course, @('m1') must eventually expand.  The following rule effectively
  makes the prover open @('m1') only when the clock is a natural number
  constant.  (We say &ldquo;effectively&rdquo; because we assume that all clock
  expressions are phrased in terms of @('clk+').)  The rule below exploits the
  fact that the prover sees @('7'), for example, as @('(+ 1 6)').</p>

  @({
  (defthm m1-opener
    (and (equal (m1 s 0) s)
         (implies (natp i)
                  (equal (m1 s (+ 1 i))
                         (m1 (step s) i)))))
  })

  <p>We then disable @('m1').</p>

  <p><b>Obscure Remark</b>: Experiments with the @('codewalker') tool (see the
  ACL2 book @('books/projects/codewalker/codewalker.lisp'), specifically the
  discussion of &ldquo;snorkling&rdquo;) suggest that nests of @('step')s more
  than several hundred deep (depending on the complexity of @('step')) can
  cause stack overflow.  One way to handle that is to modify @('m1-opener'),
  above, using a @(tsee syntaxp) hypothesis so that it doesn't fire if @('i')
  is, say, larger than 200.  Then prove a variant for &ldquo;large&rdquo;
  natural numbers, @('i'), that transforms @('(m1 s i)') into p @('(m1 (m1 s
  200) (- i 200))'), using @(tsee syntaxp) to limit the application to @('s')
  terms that are <i>not</i> calls of either @('m1') or @('step'), and @('i')
  terms that are quoted natural numbers.  This variant can be derived from
  @('m1-clk+').  (Note: a hint is necessary to keep our other rules from
  interfering with the obvious proof.)  The effect of this more sophisticated
  variant of @('m1-opener') is that an expression like @('(m1 s 900)') is
  rewritten first to @('(m1 (m1 s 200) 700)'); the sophisticated rule won't
  fire on the outer @('m1') because it is applied to an @('m1') term, but the
  conventional @('m1-opener') will fire on the inner @('(m1 s 200)') because of
  the small clock.  That will reduce the inner @('m1') to a semi-explicit
  state, and then another 200 steps will be taken from the 700, etc.  We do not
  recommend doing this until you start to get stack overflows, but we point out
  the possibility to highlight the tricks you can use to control
  expansions.</p>

  <p>But for the rest of this discussion we assume we just have the
  conventional @('m1-opener'). The rules shown above have the effect of
  rewriting the following @('m1') call successively into the last term
  below.</p>

  @({
  (m1 (make-state 0 (list n ans) stack *pi*)
      (clk+ 2 (loop-clk n)))

  =                             {by m1-clk+}

  (m1 (m1 (make-state 0 (list n ans) stack *pi*)
          2)
      (loop-clk n))

  =                             {by m1-opener}

  (m1 (step (step (make-state 0 (list n ans) stack *pi*)))
      (loop-clk n))

  =                             {by step-opener}

  (m1 (make-state 2
                  (list n 1)
                  stack
                  *pi*)
      (loop-clk n))
  })

  <p>The last simplification above is just the symbolic evaluation of the first
  two instructions of @('*pi*'), as we shown Symbolic Execution Example 1.</p>

  <p>We'll see the final @('m1') expression again later, when we prove
  @('*pi*') computes the factorial function.</p>

  <h3>Playing with Program *pi*: Execution, Symbolic Execution, and Proof of
  Correctness</h3>

  <p>In this section use program @('*pi*') to compute factorial on a concrete
  state, essentially using our formal model as a prototype of the envisioned
  machine.  We show two examples, @('n') = 6 and @('n') = 1000.  The latter
  requires several thousand @('m1') steps and allows us to time the execution
  speed of @('m1').  We then show the theorem prover doing symbolic execution
  of a snippet of @('*pi*') to help us &ldquo;reverse engineer&rdquo; the loop.
  Finally, we prove that when program @('*pi*') is run on a natural number
  @('n') in local 0, it halts and leaves @('(fact n)') on top of the stack,
  where @('fact') is defined in the classic recursive way.  In fact, we prove
  something stronger and explain why.</p>

  <h4>The Clock for Factorial</h4>

  <p>If we start at @('pc') 0, how many steps must we take to reach the
  @('halt')?  We take 2 steps to reach the instruction labeled @('loop') at
  @('pc') 2.  We'll then travel around the loop some &ldquo;unknown&rdquo;
  number of times as a function of @('n') before exiting and reaching the
  @('HALT').  (Technically the iteration might also depend on @('ans') but in
  this case it does not.)  Let @('(loop-clk n)') be the number of steps we take
  from @('pc') 2 to the @('HALT').  After defining @('loop-clk') we can define
  the clock for @('*pi*') to be</p>

  @({
  (defun clk (n)
    (clk+ 2
          (loop-clk n)))
  })

  <p>To derive a definition for @('loop-clk') just walk the code starting at
  @('pc') 2.  The code tests whether @('n') is zero and if so jump to 13 where
  it puts @('ans') on the stack and halt.  Thus, if @('n') is zero, we take 3
  steps.  If @('n') is not zero (which takes 2 steps to determine), we multiply
  @('n') into @('ans') (at @('pc')s 4-7, which takes 4 steps), decrement
  @('n') (at @('pc')s 8-11, which takes 4 steps), and then at @('pc') 12 the
  code jumps back to loop (which takes 1 step).  So after a total of 2+4+4+1 =
  11 steps we're back at @('pc') 2 having decremented @('n') by 1.  So here is
  how many steps we take from @('pc') 2 to the @('halt'):</p>

  @({
  (defun loop-clk (n)
    (if (zp n)
        3
        (clk+ 11
              (loop-clk (- n 1)))))
  })

  <p>Question: how many steps does it take to compute @('6!')?  Answer: @('(clk
  6)') = 71.</p>

  <h4>Computing with M1</h4>

  <p>If we fire up ACL2, include the @('m1') book, select the @('"M1"')
  symbol package, and define @('*pi*'), @('loop-clk'), and @('clk') as shown
  above, we can use @('m1') to compute various factorials.</p>

  @({
  M1 !>(m1 (make-state 0           ; pc
                       (list 6 0)  ; locals n = 6 and ans = 0
                       nil         ; stack (empty)
                       *pi*)       ; program
           (clk 6))
  (14 (0 720)
      (720)
      ((ICONST 1)
       (ISTORE 1)
       (ILOAD 0)
       (IFEQ 10)
       (ILOAD 1)
       (ILOAD 0)
       (IMUL)
       (ISTORE 1)
       (ILOAD 0)
       (ICONST 1)
       (ISUB)
       (ISTORE 0)
       (GOTO -10)
       (ILOAD 1)
       (HALT)))
  })

  <p>Observe the final state: the @('pc') is @('14'), which points to the
  @('(HALT)').  Local 0, i.e., @('n'), has been zeroed out but local 1, i.e.,
  @('ans'), contains @('720').  Furthermore, @('720') has been pushed onto the
  stack.  The @('program'), of course, is unchanged.  And by the way, 720 =
  6*5*4*3*2*1.</p>

  <p>Of course, we can define factorial recursively in ACL2 and check the
  @('m1') computation.</p>

  @({
  M1 !>(defun fact (n)
         (if (zp n)
             1
             (* n (fact (- n 1)))))

  The admission of FACT is trivial, ...
  ...

  M1 !>(fact 6)
  720
  })

  <p>We can compute larger factorials with @('m1'), of course.  Here's how we
  compute @('1000!') with @('m1').</p>

  @({
  M1 !>(m1 (make-state 0 (list 1000 0) nil *pi*) (clk 1000))
  })

  <p>It takes SBCL about 0.02 seconds to compute the answer.  The answer is a
  natural number with 2,568 decimal digits, so we won't show it here, but you
  can try it on your own.  @('(Clk 1000)') is 11,005, so during this particular
  computation, ACL2 was executing 550,250 M1 instructions per second.  Our
  model would run faster if we used a single-threaded object (see @('stobj'))
  to hold the state and faster still if we verified the guards of @('m1').  We
  point to discussions and examples of these ideas at the end of this
  topic.</p>

  <h4>Symbolic Execution of M1 Code</h4>

  <p>We can use the theorem prover to help us reverse engineer code.  For
  example, what does the loop in @('*pi*') do?  We actually posed the question
  in Symbolic Execution Example 2 above, i.e., what is @('(m1 (make-state
  2 (list n ans) stack *pi*) 11)') when @('n') and @('ans') are natural numbers
  and @('n') is not @('0').  We can pose a (non-)theorem to the prover to see.
  The lefthand side of the equality just simplifies to the nest of 11
  @('step')s from Symbolic Execution Example 2.  The righthand side, below, is
  the variable @('???'), so this formula is obviously not a theorem, but the
  prover will simplify the formula and print the checkpoint.</p>

  @({
  (thm (implies (and (natp n)
                     (< 0 n)
                     (natp ans))
                (equal (m1 (make-state 2 (list n ans) stack *pi*) 11)
                       ???)))
  })

  <p>Of course, the proof attempt fails.  But if you look at the checkpoint you
  should recognize the simplified expression as being from Example 2.</p>

  @({
  Goal''
  (IMPLIES (AND (INTEGERP N)
                (<= 0 N)
                (< 0 N)
                (INTEGERP ANS)
                (<= 0 ANS))
           (EQUAL (MAKE-STATE 2 (LIST (+ -1 N) (* ANS N))
                              STACK
                              '((ICONST 1)
                                (ISTORE 1)
                                (ILOAD 0)
                                (IFEQ 10)
                                (ILOAD 1)
                                (ILOAD 0)
                                (IMUL)
                                (ISTORE 1)
                                (ILOAD 0)
                                (ICONST 1)
                                (ISUB)
                                (ISTORE 0)
                                (GOTO -10)
                                (ILOAD 1)
                                (HALT)))
                  ???))
  })

  <h4>Proving Theorems about M1 Programs</h4>

  <p>In this section we prove that @('*pi*') computes factorial.</p>

  <p><b>Step 0: The Specification</b> We've already specified, informally, that
  we intend that @('*pi*') computes @('(fact n)') when @('n') is a natural
  number.  This is just shorthand for the more precise understanding that if we
  start at @('pc') 0 with a natural, @('n'), in local 0 and run program
  @('*pi*') @('(clk n)') steps, the final state has @('pc') 14 (meaning
  execution reached the @('(HALT)')), local 0 has been zeroed, local 1 contains
  @('(fact n)'), and @('(fact n)') is on top of the otherwise unchanged initial
  @('stack').</p>

  <p><b>Step 1: The Semantic Function</b> Define an ACL2 function that
  &ldquo;does what the loop does.&rdquo; We sometimes call this the <i>semantic
  function</i> corresponding to the loop.</p>

  @({
  (defun helper (n ans)
    (if (zp n)
        ans
        (helper (- n 1) (* ans n))))
  })

  <p>The function above captures @('*pi*')'s behavior from entry to the loop at
  @('pc') 2 through the halt at @('pc') 14.  Programs that have elaborate
  initialization and finalizations and/or multiple loops require defining a
  series of functions for each segment and loop.  But for this program, we can
  capture all of @('*pi*')'s behavior by calling the semantic function on the
  values the locals have upon entering the loop, i.e., @('(helper n 1)').</p>

  <p><b>Step 2: Relate the Semantic Function to the Code</b> Prove that the loop
  does what we said it would do.</p>

  @({
  (defthm loop-correct
    (implies (and (natp n)
                  (natp ans))
             (equal (m1 (make-state 2
                                    (list n ans)
                                    stack
                                    *pi*)
                        (loop-clk n))
                    (make-state 14
                                (list 0 (helper n ans))
                                (push (helper n ans) stack)
                                *pi*))))
  })

  <p>This proof is completely &ldquo;automatic&rdquo; &mdash; but only because
  we stated the theorem exactly right, in terms of @('helper') to
  &ldquo;explain&rdquo; what the loop is doing with the second local, @('ans').
  Once you get used to this style of proof, Step 2 is not really very creative:
  it just says what the program does operationally, using tail recursion in
  place of iteration.  Of course, recursion is ACL2's bread and butter.</p>

  <p>The proof of @('loop-correct') is by the induction as suggested by
  @('(helper n ans)').  The induction scheme is</p>

  @({
  (AND (IMPLIES (AND (NOT (ZP N))
                     (:P (* ANS N) (+ -1 N) STACK))
                (:P ANS N STACK))
     (IMPLIES (ZP N) (:P ANS N STACK)))
  })

  <p>If you work it out you'll see that in the induction conclusion
  @('(loop-clk n)') expands to @('(clk+ 11 (loop-clk (- n 1)))'), and then the
  machinery we've been talking about reduces the induction conclusion to the
  induction hypothesis.  Do it for yourself.  You will see the simplifications
  done earlier in Symbolic Execution Example 2.  (There is another basic case
  we haven't explicitly discussed: what happens when we're at the top of the
  loop but @('n') is @('0')?  That case is handled by symbolic execution:
  @('(loop-clk n)') is 3, the @('IFEQ') jumps to the exit to push @('ans') onto
  the stack and advance the @('pc') to the @('(HALT)') at 14.)  </p>

  <p><b>Step 3: Relate the Semantic Function to the Specification</b></p>


  @({
  (defthm helper-is-fact
    (implies (and (natp n)
                  (natp ans))
             (equal (helper n ans)
                    (* ans (fact n)))))
  })

  <p>This is proved &ldquo;automatically.&rdquo;</p>

  <p>Generally speaking, Step 3 is the most creative step because it requires
  explaining how the &ldquo;iterative&rdquo; (tail-recursive) accumulation of
  the answer relates to the recursive computation of the answer.</p>

  <p><b>Step 4: Total Correctness</b> Combine the foregoing into the statement
  of the total correctness of @('*pi*').</p>

  @({
  (defthm correctness-of-*pi*
    (implies (natp n)
             (equal (m1 (make-state 0
                                    (list n ans)
                                    stack
                                    *pi*)
                        (clk n))
                    (make-state 14
                                (list 0 (fact n))
                                (push (fact n) stack)
                                *pi*))))
  })

  <p>This is proved &ldquo;automatically&rdquo; because of our setup.</p>

  <p>@('(Clk n)') expands to @('(clk+ 2 (loop-clk n))') and the crucial
  @('m1-clk+') (&ldquo;sequential execution&rdquo;) rule shows it is equivalent
  to</p>

  @({
  (m1 (step (step (make-state 0
                              (list n ans)
                              stack
                              *pi*)))
      (loop-clk n))
  })

  <p>But then the @('step') rules can reduce that to:</p>

  @({
  (m1 (make-state 2
                  (list n 1)
                  stack
                  *pi*)
      (loop-clk n))
  })

  <p>at which point the @('loop-correct') lemma can fire and produce</p>

  @({
  (make-state 14
              (list 0 (helper n 1))
              (push (helper n 1) stack)
              *pi*)
  })

  <p>and then @('(helper n 1)') is rewritten @('(fact n)') by @('helper-is-fact') and
  arithmetic, reducing the lefthand side to the righthand side.  (The above description
  is inaccurate only in the sequencing of the various rewrites.)  Q.E.D.</p>

  <p>Of course, from @('correctness-of-*pi*') we can easily derive weaker but
  simpler results to &ldquo;advertise.&rdquo;</p>

  @({
  (defthm corollary-of-correctness-of-*pi*
    (implies (and (natp n)
                  (equal s_init (make-state 0 (list n ans) stack *pi*))
                  (equal s_fin (m1 s_init (clk n))))
             (and (equal (top (stack s_fin)) (fact n))
                  (equal (next-inst s_fin) '(HALT)))))

  })

  <p>Viewing these results from a higher level, one might argue that the
  corollary above is a &ldquo;better&rdquo; theorem than
  @('correctness-of-*pi*').  It just says, simply, if you have an initial state
  poised to execute @('*pi*') on @('n') and you run it @('(clk n)') steps to
  some &ldquo;final&rdquo; state, that final state has @('(fact n)') on top of
  the stack and is halted.  The full correctness result we proved says some
  &ldquo;irrelevant&rdquo; things: in the final state, @('n') is 0, @('(fact
  n)') is also in local 1, and the original stack is intact under the
  answer.</p>

  <p>But those facts are not irrelevant!  They (or something like them) are
  mathematically necessary for the inductive proof.  Remember, inductive proofs
  only work on sufficiently strong theorems.  Furthermore, we really must care
  about these other issues even from the high level perspective.  If, for
  example, our program is just a subroutine of a larger system (on a machine
  that supports procedure call and return) we <i>really need to know</i> that
  the stack is not disturbed since the results of prior computations may be
  sitting in it for use for future computations.  In a setting where we're
  concerned about privacy and security (in a machine with addressable memory)
  <i>we really need to know</i> that information hasn't been moved from private
  space to public space.  In a setting where programs are in writable memory,
  <i>we really need to know</i> that our program hasn't been overwritten by
  some subroutine.</p>

  <h3>More M1 Programs and Proofs</h3>

  <p>The proofs described above can be seen in the ACL2 book
  @('books/models/jvm/m1/fact.lisp').  If the proof script here is taken as a
  template for all such proofs you'll find it a bit &ldquo;fragile&rdquo; in
  the sense that lemmas proved in one step of the template may get in the way
  of proofs in subsequent steps.  That is generally dealt with by disabling
  certain lemmas when their work has been done.  But, except for this issue of
  controlling rewriting a little more restrictively via disabling, this proof
  of the correctness of @('*pi*') serves as a good template for clock-based
  total correctness proofs of single-loop @('m1') programs.</p>

  <p>There are many other examples of proofs of @('m1') programs on the
  directory @('books/models/jvm/m1').  Here is a brief guide.</p>

  <ul>

  <li>@('books/models/jvm/m1/template.lisp'): a &ldquo;robust&rdquo; template
  for proving the total correctness of one-loop @('m1') programs.  The template
  is overly robust in the sense that it introduces often irrelevant
  intermediate functions, lemmas, and disable events.  In the vast majority of
  cases the proofs can be carried out with fewer events.  But until you
  understand how ACL2 behaves it's best to just rotely follow the
  template.</li>

  <li>the files listed below contain simple one-loop @('m1') programming and
  proof challenges.  Each file follows the template above.  We recommend that
  you <i>not</i> look at the solutions and instead read the challenge
  programming/proof problem at the top of the file and then follow the template
  for yourself.  We also recommend you do these problems in the order listed,
  as they gradually get harder.
  <ul>
  <li>@('books/models/jvm/m1/sum.lisp')</li>
  <li>@('books/models/jvm/m1/sumsq.lisp')</li>
  <li>@('books/models/jvm/m1/fact.lisp')</li>
  <li>@('books/models/jvm/m1/power.lisp')</li>
  <li>@('books/models/jvm/m1/expt.lisp')</li>
  <li>@('books/models/jvm/m1/alternating-sum.lisp')</li>
  <li>@('books/models/jvm/m1/alternating-sum-variant.lisp')</li>
  <li>@('books/models/jvm/m1/fib.lisp')</li>
  <li>@('books/models/jvm/m1/lessp.lisp')</li>
  <li>@('books/models/jvm/m1/even-solution-1.lisp')</li>
  <li>@('books/models/jvm/m1/even-solution-2.lisp')</li>
  <li>@('books/models/jvm/m1/sign.lisp')</li> </ul> </li>

  <li>the files below deal with two-loop programs in which the loops are
  nested.  The solutions use the same basic naming scheme as the template.

  <ul>
  <li>@('books/models/jvm/m1/div.lisp')</li>
  <li>@('books/models/jvm/m1/bexpt.lisp')</li>
  </ul>
  </li>

  <li>@('books/models/jvm/m1/m1-fact-on-neg-runs-forever.lisp'): we prove
  that if @('n') is negative, the factorial program @('*pi*') never reaches the
  halt.  This problem is probably not suitable for you to work out on your own.
  But you can probably do others like it after understanding the proofs here.
  We prove the theorem two different ways.  The first is a classic clock-style
  proof but the clock function decomposes an arbitrary natural number @('k >
  1') into the form 2 + 11 + 11 + ... + 11 + @('(mod (- k 2) 11)') and then an
  inductive proof shows that the program never gets out of the loop &mdash; and
  there's no @('HALT') in the loop.  The second uses the inductive assertion
  style proof carried out directly by symbolic evaluation of the operational
  semantics and induction.  For an explanation of the use of inductive
  assertions with this style of operational semantics see @(see bib::moore03b).
  That paper deals with the M5 machine (ACL2 directory
  @('books/models/jvm/m5/')) but is easily understood in the context of
  M1.</li>

  <li>@('books/models/jvm/m1/m1-half-via-inductive-assertions.lisp'): define
  a program that halves its natural number input and terminates iff the input
  was even.  Prove it.  This example is discussed in @(see bib::moore03b) as an
  M5 program.  It uses the inductive assertion method.</li>

  <li>@('books/models/jvm/m1/magic.lisp') illustrates the importance of
  termination.  It presents a program that just successively replaces the top
  of the stack by its successor, starting from @('0').  If you look at the
  state at the right moment, you can find any natural number you want on top of
  the stack.  So this program &ldquo;implements&rdquo; every natural valued
  function &mdash; if terminating isn't a requirement!  In that sense, we prove
  this program implements fib and also implements factorial.  (Of course, we
  could also constrain a function to return a natural and prove that the
  program implements that function, but we don't bother.)</li>

  <li>@('books/models/jvm/m1/funny-fact.lisp'): this shows a two-loop program
  in which one loop follows another rather than being nested inside the other.
  The first loop pushes successive naturals from @('n') down to @('1') onto the
  stack.  The second loop repeatedly multiplies the top two elements together.
  Prove that implements factorial.  Note: this &ldquo;bytecode&rdquo; program
  violates a basic principle of the Java bytecode verifier, which insists that
  the stack is always the same length upon every arrival at every
  instruction.</li>

  <li>@('books/models/jvm/m1/wormhole-abstraction.lisp'): yet another proof
  of a factorial program, but it shows a way you can avoid explicitly
  specifying intermediate values you don't care about.  This idea was first
  demonstrated by Dave Greve of Collins Aerospace.</li>

  <li>@('books/models/jvm/m1/m1-with-stobj.lisp'): @('M1') has been defined in
  a &ldquo;constructor&rdquo; style: every new state constructed as a list of
  four elements where all the elements are specified.  In more realistic
  machines, e.g., ACL2 directory @('books/projects/x86isa/'), the state is a
  single-threaded object (see @(see stobj)) that is destructively modified to
  effect state changes.  This produces much more efficient runtime execution.
  However, it slightly changes the form of correctness proofs.  In
  @('m1-with-stobj.lisp') we define the M1 machine using a single-threaded
  object as the state.  Then, in<p/>

  <ul>
  <li>@('books/models/jvm/m1/m1-with-stobj-clock-example.lisp')</li>
  </ul>

  we implement multiplication by repeated additions (avoiding use of the
  @('IMUL') instruction) on that version of M1 and prove it correct.</li>

  <li>@('books/models/jvm/m1/defsys.lisp'): a verifying compiler from a very
  simple &ldquo;Toy Lisp&rdquo; to @('m1').  Toy Lisp is just the subset of
  ACL2 composed of variable symbols, quoted numeric constants, the function
  symbols @('+'), @('-'), @('*') (primitively supported by M1), the form @('(MV
  a1 ... an)') for returning multiple values, the form @('(IFEQ a b c)') (which
  is just ACL2's @('(if (equal a 0) b c)')), and calls of primitive and defined
  Toy Lisp functions.  The compiler takes a list of Toy Lisp
  &ldquo;modules,&rdquo; each of which specifies a symbolic name, formals,
  pre-conditions, post-conditions, and a Toy Lisp implementation.  An example
  module is

  @({
  (lessp :formals (x y)
         :input (and (natp x)           ; pre-condition
                     (natp y))
         :output (if (< x y) 1 0)       ; post-condition
         :code (ifeq y                  ; Toy Lisp implementation
                     0
                     (ifeq x
                           1
                           (lessp (- x 1) (- y 1)))))
  })

  The compiler implements a call/return protocol so that one Toy Lisp function
  can use another.  The compiler produces M1 code for each module.  In
  addition, it produces the clock function for each module and it generates
  events that prove that the M1 code implements input/output specification.
  The result is an M1 state poised to call the module @('main') on whatever
  arguments are on the @('m1') @('stack'). <b>Warning:</b> As of August, 2024,
  the comments in @('defsys.lisp') are out of date!</li>

  <li>@('books/models/jvm/m1/theorems-a-and-b.lisp'):  a proof that M1
  can compute anything a Turing machine can compute.  See the paper
  @(see bib::moore14).</li>

  <li>The ACL2 file @('books/projects/codewalker/README') describes a tool
  called &ldquo;codewalker.&rdquo; Codewalker is a utility for exploring code
  in any programming language specified by an ACL2 operational model.  Three
  main facilities are provided: the abstraction of a piece of code into an ACL2
  &ldquo;semantic function&rdquo; that returns the same machine state, the
  definition the &ldquo;clock function&rdquo; for the code, and the
  &ldquo;projection&rdquo; of the semantic function into another function that
  computes the final value of a given state component using only the values of
  the relevant initial state components.  No paper about codewalker is
  available.  But the first 50 pages of @('codewalker.lisp') is a comment
  providing documentation.  In addition, several examples are provided in other
  files.  For example, the ACL2 book
  @('books/projects/codewalker/demo-fact.lisp') uses codewalker to verify an M1
  factorial program.  By the way, the version of M1 used there is defined on
  the @('codewalker/') directory rather than the @('books/models/jvm/m1/')
  directory to allow the two versions to drift apart.  The M1 used by the
  codewalker demo is defined in
  @('books/projects/codewalker/m1-version-3.lisp') and it uses a
  single-threaded object (see @(see stobj)) representation of the state.</li>

  </ul>

  <h3>More Elaborate Models of the JVM: From M1 to M6</h3>

  <p>M1 is only the start of a series of models of the JVM.  M1 lacks
  a bytecode verifier, method invocation, threads, and other features
  which are explored in the more elaborate models, all of which are
  found on the ACL2 directory @('books/models/jvm/').</p>

  <ul>

  <li>The ACL2 directory @('books/models/jvm/guard-verified-m1/') is another
  version of @('m1') that differs in two ways.  First, instead of using the
  constructor style of creating new states (e.g., with @('(list pc locals stack
  program)')) it uses a single-threaded object (see @(see stobj)).  This
  slightly changes the forms of correctness theorems and lemmas.  Second, the
  definition of @('m1') on the @('books/models/jvm/guard-verified-m1/')
  directory has been guard verified.  This involves attaching a guard to every
  &ldquo;@('execute')&rdquo; function and lifting that up to the level of the
  @('m1') function.  The guards include the notion of a &ldquo;good
  state&rdquo; which includes the notion of a well-formed program.  But that
  necessarily involves the requirement that, say, when every @('IADD')
  instruction is encountered the stack has at least two numbers on it.  The
  @('good-statep') predicate is essentially a simple <i>bytecode verifier</i>
  for @('m1'): it tells us that if a state is good (meaning, the program in it
  is good), then executing the program guarantees all the properties necessary
  for error-free execution.  Verifying the guards of this version of @('m1')
  demonstrates &ldquo;verification of the bytecode verifier.&rdquo; The
  directory also contains the examples found in the unguarded version of
  @('m1') on @('books/models/jvm/m1').  The reason we provide two functionally
  equivalent versions of @('m1') is that when teaching how to use ACL2 to
  specify a machine operationally, it is easiest to start with the unguarded
  @('m1').</li>

  <li>M2, on the ACL2 directory @('books/models/jvm/m2/') is essentially M1
  with method invocation (both static and virtual), return, and class instances
  including a demonstration of inheritance.  See @(see bib::moore99a).  In that
  paper the machine is named &ldquo;tjvm&rdquo; for &ldquo;Toy JVM&rdquo; but
  its proper name is M2.  The paper and ACL2 scripts illustrate how to reason
  about procedure call and return.</li>

  <li>M5, on the ACL2 directory @('books/models/jvm/m5/') is a closer
  approximation to the JVM.  M5 was written by George Porter, as an
  undergraduate project.  M5 supports 195 JVM instructions, including those for
  several kinds of arithmetic, arrays, and objects, threads and monitors.  The
  handling of integer arithmetic is accurate, e.g., all integers are bounded
  and addition, say, wraps around.  Floating point is not accurate and we
  regard it as a mere placeholder.  The directory contains proofs of properties
  for several M5 programs, including iterative and recursive ones (dealt with
  via clock-based proofs), some partial correctness proofs about programs that
  do not always terminate (dealt with via the inductive assertion method), and
  the correctness of an applicative insertion sort method (on Objects
  representing cons trees).  See @(see bib::mp02) and @(see bib::moore03a).  A
  proof of a mutual-exclusion property, called &ldquo;the Apprentice
  Challenge,&rdquo; is described in the papers and the corresponding books
  containing proofs are available on the @('m5/') directory.</li>

  <li>M6, on the ACL2 directory @('books/models/jvm/m6/') is the best
  approximation to the JVM.  M6 was written as part of Hanbing Liu's PhD
  dissertation, supported by Sun Microsystems.  The M6 state includes an
  &ldquo;external class table&rdquo; where classes reside until they are
  loaded.  M6 can execute most J2ME Java programs (except those with
  significant I/O or floating-point).  It was primarily designed to model
  dynamic class loading, class initialization, and bytecode verification.  The
  entire Sun CLDC API library (672 methods in 87 classes) was translated into
  the external representation and is available for loading, constituting about
  500 pages of data.  The model included 21 out of 41 native APIs that appeared
  in Sun's CLDC API library.  The M6 description itself is about 160 pages of
  ACL2.  See @(see bib::liu06).</li>

  </ul>

  <h3>Quick Index to Related Topics</h3>
  <ul>
  <li>@(see operational-semantics)</li>
  <li>operational-semantics-1__simple-example &mdash; current topic</li>
  <li>@(see operational-semantics-2__other-examples)</li>
  <li>@(see operational-semantics-3__annotated-bibliography)</li>
  <li>@(see operational-semantics-4__how-to-find-things)</li>
  <li>@(see operational-semantics-5__history-etc)</li>
  </ul> ")
other
(defxdoc operational-semantics-2__other-examples
  :parents (operational-semantics)
  :short "Examples of other models and proof techniques"
  :long "<p>The topic @(see operational-semantics-1__simple-example) deals with
  a simple machine, M1, and focuses on the &ldquo;clock&rdquo;-based proof
  style.  In this section we point to other machine models, different ACL2
  proof styles, and tools in the ACL2 Community Books that may be of
  interest.</p>

  <p>We limit our discussion here to operational semantics.  But it is worth
  noting that a valuable way to explore the diversity of ACL2 applications and
  extensions is to browse the ACL2 Workshop series.  See the &ldquo;ACL2
  Workshops, UT Seminar, and Course Materials&rdquo; link on the <a
  href='http://www.cs.utexas.edu/users/moore/acl2/'>ACL2 homepage</a>.  Then
  visit the Program for each workshop.  Many of the papers include supplemental
  material in the form of ACL2 proof scripts are in the ACL2 Community Books
  regression suite and thus available locally if you've installed ACL2.
  They're under the directory @('books/workshops/'), which is organized by the
  year of the workshop and the name of the author(s), e.g.,
  @('books/workshops/2023/passmore/').</p>

  <h3>Other Machines</h3>

  <p>As noted in @(see operational-semantics-5__history-etc), a &ldquo;handheld
  calculator&rdquo; was formalized in Chapter 17 @(see bib::bm79), using the
  precursor to Nqthm.  That machine was essentially M1 without the branch or
  jump instructions.  That is, all programs were just straightline sequences of
  stack-based arithmetic operations.  The Bendix 930 flight control computer
  discussed in @(see bib::bm80) was a more traditional von Neumann machine,
  also modeled in the precursor to Nqthm.  The 30 page model is listed in
  Section 15 of @(see bib::bm80).</p>

  <p>The Computational Logic, Inc. (CLI) Verified Stack was formalized and
  verified with Nqthm.  The CLI Verified Stack was a hardware-software stack
  consisting of a gate-level description of a microprocessor, its instruction
  set architecture, an assembler/linker/loader for a stack based assembly
  language with subroutine call and return, a compiler for a simple subset of a
  Pascal-like language, a simple operating system kernel, and some applications
  programs.  Each component of the stack was verified with respect to the
  component immediately below in such a way that the correctness theorems could
  be composed.  The result was that if a program in the high-level language was
  verified (with respect to the operational semantics of the high-level
  language) then compiling, assembling, linking, and loading the binary image
  onto the gate-level machine and running it would, with mathematical
  certainty, deliver the results verified at the high level.  The stack was
  described in the 1989 special issue of the <i>Journal of Automated
  Reasoning</i>, @(see bib::bhmy89).  In 1992, a hardware description language
  was formalized and another microprocessor was described and verified to
  implement a slightly different machine code.  That microprocessor was
  fabricated, the assembler/linker/loader was retargeted to the new machine
  code and verified, so that the entire stack was then ported to a fabricated
  microprocessor.  A second compiler (for a Lisp subset) and a game-playing
  applications program were also written and verified.  The CLI Stack was a
  project by Bill Bevier, Bishop Brock, Art Flatau, Warren A. Hunt, Jr., Matt
  Kaufmann, J Moore, Matt Wilding, and Bill Young, of Computational Logic,
  Inc.</p>

  <p>The CLI Verified Stack convinced us that this style of operational
  semantics was viable not just for program verification but for stacking and
  relating machines.  For more details, including papers, books, dissertations,
  and proof scripts, start at the annotation for @(see bib::bhmy89) and visit
  the citations.</p>

  <p><i>[Personal aside by Moore: I believe the CLI Verified Stack to be a
  seminal achievement in formal methods.]</i></p>

  <p>The most elaborate machine model created with Nqthm was of the Motorola
  MC68020, modeled by Yuan Yu @(see bib::yu92).  He and Boyer used that model
  to verify many MC68020 machine code programs produced by a variety of
  standard compilers.  Perhaps most notably they verified the machine code for
  Hoare's Quick Sort and 21 of the 22 functions in the Berkeley Unix C string
  library (as compiled with @('gcc -o')).  For a shorter description of the
  work, see @(see bib::by96).</p>

  <p>Of course, state machines are not limited to modeling computational
  engines.  See @(see bib::bgm90) for a real-time control problem formalized
  with a &ldquo;clocked&rdquo; state machine where the &ldquo;clock&rdquo;
  specifies the change in the physical environment at each sampling cycle.  In
  addition, games can often be formalized with state machines where the
  &ldquo;clock&rdquo; specifies opponents' moves.  Strategies can be analyzed
  via proof.  See the Nqthm script analyzing the game of Tic Tac Toe,
  @('examples/basic/tic-tac-toe.events') or @(see bib::wilding93) for a
  description of the verification of a winning strategy for the game of Nim.
  See the ACL2 scripts for playing Towers of Hanoi, @(see
  Tutorial1-Towers-of-Hanoi), @('books/misc/hanoi.lisp'), and the Bottle
  Game (played in the 1995 movie <i>Die Hard 2</i>),
  @('books/projects/die-hard-bottle-game/top.lisp').</p>

  <p>But for the rest of this discussion we focus on modeling and proving
  properties of compute engines with ACL2.</p>

  <p>The first major external applications of ACL2 after it was developed at
  Computational Logic, Inc., were at Motorola Government Systems, in
  Scottsdale, Arizona, between 1993 and 1997, and at Advanced Micro Devices,
  Inc. (AMD), in Austin, Texas, in 1995.  Only the first of these two projects
  employed operational semantics &mdash; and it was a <i>tour de force</i>.</p>

  <p>A CLI employee, Bishop Brock, relocated to Scottsdale and embedded with a
  design group there to formalize the evolving design of the Motorola
  &ldquo;Complex Arithmetic Processor&rdquo; (CAP) digital signal
  processor (DSP), using the operational semantic techniques developed with
  Nqthm and described above.  A timeline of the entire ACL2 part of the CAP DSP
  project may be found in @(see bib::bkm96).</p>

  <p>Here is a brief description of the CAP design taken from Section 2.1
  of @(see bib::bkm96).</p>

  <blockquote>
  <p>The CAP design follows the `Harvard architecture', i.e., there are
  separate program and data memories.  The design includes 252
  programmer-visible data and control registers.  There are six independently
  addressable data and parameter memories.  The data memories are logically
  partitioned into `source' and `destination' memories; the sense of the
  memories may be switched under program control.  The arithmetic unit
  includes four multiplier-accumulators and a 6-adder array.  The CAP
  executes a 64-bit instruction word, which in the arithmetic units is
  further decoded into a 317-bit, low-level control word.  The instruction
  set includes no-overhead looping constructs and automatic data scaling.  As
  many as 10 different registers are involved in the determination of the
  next program counter.  A single instruction can simultaneously modify well
  over 100 registers.  In practice, instructions found in typical
  applications simultaneously modify several dozen registers.  Finally, the
  CAP has a three-stage instruction pipeline which contains many
  programmer-visible pipeline hazards.</p>

  </blockquote>

  <p>Brock, with help from Warren Hunt, J Moore, and Matt Kaufmann, developed a
  bit- and cycle-accurate model of the CAP design.  We believe this was the
  first time an entire commercial microprocessor was formally specified, see
  @(see bib::bh99).</p>

  <p>Brock validated the design by running the ACL2 model against Motorola's
  SPW engineering model of the processor.  For example, he compared the results
  of executing an end-to-end application (a QPSK modem) on both the SPW model
  and the ACL2 model and found the final states bit-exact for all programmer
  visible registers.</p>

  <p>Before turning to the verification of CAP applications programs Brock
  undertook the logical elimination of the CAP pipeline.  He defined a
  predicate that syntactically detected pipeline hazards in microcode and he
  implemented a simpler ACL2 machine model without the pipeline.  Then,
  following Burch and Dill's method of comparing states after flushing the
  pipeline via symbolic evaluation, he proved with ACL2 that the two models
  were equivalent <i>provided the microcode was hazard free</i>.</p>

  <p>Then Brock, <i>et al</i>, proved several microcode programs correct, again
  following the proof methodology we sketched in section &ldquo;Proving
  Theorems about M1 Programs&rdquo; of
  @('operational-semantics-1__simple-example'), where the main subtasks were
  our so-called Steps 2 and 3: verify that the execution of the pipeline-free
  model on hazard-free microcode implements semantic function of the program,
  and then verify that the semantic function implements the more abstract
  specification.  An example of the second (generally harder) step is described
  in @(see bib::bm05). These two results could then be chained together, along
  with the verification (by execution) that the hazard predicate detected no
  hazards in the microcode and the proof of the equivalence (modulo the absence
  of hazards) of the pipelined and non-pipelined models, to conclude that the
  microcode runs correctly on the pipelined model.</p>

  <p>It is noteworthy that ACL2 executed the pipeline-free microcode
  interpreter several times faster than the hardware simulator could execute
  the SPW model &mdash; with assurance that the answers were equivalent to the
  pipelined model on hazard-free microcode.  In addition, the ACL2 hazard
  predicate, being an executable ACL2 function on microcode programs, 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 @(see bib::bh99).  This can be considered another practical application
  of formal methods since the hazard detection predicate was formally verified
  to be a sufficient condition for the pipelined and non-pipelined machines to
  be equivalent.</p>

  <p>Unfortunately, Motorola canceled the entire CAP effort before the device
  was fabricated, despite the success of the formal methods component of the
  project. The ACL2 proof scripts are not in the ACL2 Community Books
  regression suite.</p>

  <p>We now move on to other operational models.  In @(see
  operational-semantics-1__simple-example) (and on the ACL2 directory
  @('books/models/jvm/m1/')) we describe a very simple operational definition
  of a machine, called M1, supporting a little stack-based arithmetic and some
  branch instructions.  That machine was used to teach students how to
  formalize machines and verify their programs.  M1 was the beginning of an
  evolutionary sequence of machines approximating an accurate model of the Java
  Virtual Machine.  The machines in that evolutionary sequence show how we
  can formalize and reason about method invocation (virtual and static),
  return, object creation including inheritance, threads, dynamic class
  loading, and bytecode verification.  The machines are described, with
  appropriate citations to papers and ACL2 books, in the final section of @(see
  operational-semantics-1__simple-example).</p>

  <p>The use of the inductive assertion method with an operational semantics of
  this style is quite interesting.  As noted in @(see bib::mmrv06), no other
  tools are required beyond the operational semantics and a theorem prover.  It
  is possible for the theorem prover to use the operational semantics directly
  to generate and prove the &ldquo;verification conditions&rdquo; one gets by
  exploring all possible program paths between assertions in the code.  One can
  use the method to prove either partial or total correctness, the former
  meaning &ldquo;correct if it terminates&rdquo; and the latter meaning
  &ldquo;terminating and correct at termination.&rdquo;</p>

  <p>The most complicated machine formalized (as of 2024) with ACL2 is the x86
  instruction set architecture.  The model evolved from simpler models,
  exploiting lessons learned from earlier Nqthm and ACL2 work.  In the case of
  x86, the &ldquo;toy&rdquo; was the y86 as informally described in @(see
  bib::boh03).  The ACL2 directory @('books/models/y86/') contains several
  models of the 32-bit y86 described in the First Edition of @(see bib::boh03).
  In particular, see the ACL2 book
  @('books/models/y86/y86-basic/y86/y86.lisp'), by Warren Hunt, for the model.
  For a proof of correctness of Sean Anderson's bit twiddling &ldquo;population
  count&rdquo; in y86 machine code, see the ACL2 book
  @('books/models/y86/y86-basic/py86/popcount.lisp').  The proof of that
  particular straightline piece of code is just by symbolic evaluation and the
  ACL2 verified &ldquo;bit-blasting&rdquo; solver @(see GL) by Sol Swords.</p>

  <p>From the y86, the model of the x86 evolved through several iterations
  reported in @(see bib::hk12), @(see bib::ghk13), and @(see bib::ghkg14), to
  Shilpi Goel's monumental x86 model @(see bib::goel16) and @(see bib::ghk17).
  The model specifies over 400 x86 instructions and the model includes
  architectural features like segmentation and paging.  It can be executed in
  either of two modes. When running in the application-program level, it
  executes about 3.3 million x86 instructions per second.  When running in the
  system-level mode it executes about 912,000 x86 instructions per second.  The
  model has been validated extensively against actual x86 hardware, which is
  the reason so much attention has been paid to execution efficiency.  X86
  machine code programs have been verified.  See @(see bib::goel16) and @(see
  bib::ghk17).</p>

  <h3>Proof Methods and Tools</h3>

  <p>The paper @(see bib::moore99b) shows how we can reason about a system
  involving multiple processes interacting with a shared memory.  The paper
  describes two operational models, one in which the model switches between
  multiple processes according to an &ldquo;oracle&rdquo; and the other which
  models just a single process but in which the memory changes
  &ldquo;spontaneously.&rdquo; The two models are then related by proved lemmas
  so that one can switch back and forth between views.  The lemmas are used to
  verify a safety property (using one model) and a progress property (using the
  other).  All the proofs are carried out via the clock-based methodology.</p>

  <p>We have focused on the clock-based proof methodology.  But an advantage of
  creating &ldquo;toy&rdquo; models is that it is easy to explore other proof
  methodologies and then try to apply them to larger models.</p>

  <p>The papers @(see bib::rm04) and @(see bib::rhmm07) establish that the
  clock-function approach to verification is equivalent to the use of inductive
  assertions and to stepwise invariants.  In fact, ACL2 tools are provided for
  converting between clock-based proofs and inductive assertion-style proofs.</p>

  <p>The paper @(see bib::sawada00) describes the modeling and verification of
  a pipelined machine.  The paper @(see bib::manolios00) shows an alternative
  method based on Well-founded Equivalence Bisimulations.  Briefly, it
  introduces a notion of correctness that implies that the instruction set
  architecture and micro-architecture machines have the same observable
  infinite paths, up to stuttering.</p>

  <p>The paper @(see bib::sh98) deals with a machine with precise exceptions and
  speculative execution.</p>

  <p>An ACL2 tool to help manage states in operational models is described in
  @(see bib::moore15) and a tool for determining whether two symbolic terms
  representing machine addresses may be equal is described in @(see
  bib::moore17).  These tools are available among the ACL2 Community Books.  A
  tool for deriving the meaning of and clock function for a piece of code from
  the code and the operational semantics model is described in the ACL2 file
  @('books/projects/codewalker/README').</p>

  <h3>Quick Index to Related Topics</h3>
  <ul>
  <li>@(see operational-semantics)</li>
  <li>@(see operational-semantics-1__simple-example)</li>
  <li>operational-semantics-2__other-examples &mdash; current topic</li>
  <li>@(see operational-semantics-3__annotated-bibliography)</li>
  <li>@(see operational-semantics-4__how-to-find-things)</li>
  <li>@(see operational-semantics-5__history-etc)</li>
  </ul>")
other
(defxdoc operational-semantics-3__annotated-bibliography
  :parents (operational-semantics)
  :short "Annotated bibliography for operational-semantics"
  :long "<p>This topic provides proper bibliographic citations to the work
  mentioned in the ACL2 documentation topic @(see operational-semantics) and
  its subtopics.  Each citation (e.g., @(see bib::bhmy89)) is a link, at which
  you may find additional information about the publication and its relation to
  operational semantics.  When Nqthm or ACL2 files are mentioned you will have
  to dereference those names following the instructions in @(see
  operational-semantics-4__how-to-find-things).</p>

  <h3>Quick Index to Related Topics</h3>
  <ul>
  <li>@(see operational-semantics)</li>
  <li>@(see operational-semantics-1__simple-example)</li>
  <li>@(see operational-semantics-2__other-examples)</li>
  <li>operational-semantics-3__annotated-bibliography &mdash; current topic</li>
  <li>@(see operational-semantics-4__how-to-find-things)</li>
  <li>@(see operational-semantics-5__history-etc)</li>
  </ul>

")
other
(defxdoc operational-semantics-4__how-to-find-things
  :parents (operational-semantics)
  :short "Citation conventions for doc operational-semantics"
  :long "<p>In the documentation topic @(see operational-semantics) and its
  supporting subtopics, references to published books and papers appear as
  ordinary documentation topics, except all the labels are in the "BIB"
  package, e.g., @(see bib::mccarthy62) or @(see bib::kmm00a).  When finding
  them with the @(':')@(tsee doc) keyword command or in the @(see acl2-doc)
  Emacs-based browser, you must type the &ldquo;bib::&rdquo; prefix.  When
  finding them in the &ldquo;Jump to&rdquo; box of your browser you must not
  include the &ldquo;bib::&rdquo; prefix.</p>

  <p>In @(see operational-semantics) and its supporting subtopics we also make
  frequent reference to Nqthm and ACL2 directories and proof scripts, such as
  @('examples/hunt/fm8501.events') and @('books/projects/x86isa/').  In this
  topic we explain how to dereference those citations to find the directory or
  file we mean.</p>

  <p>By the way, the active development of Nqthm ended in 1992, three years
  after ACL2 development began.  For about 10 years Nqthm and ACL2 were both in
  use.  Since then Nqthm has been maintained by Boyer and most of its proof
  scripts are not only still available but can still be processed.</p>

  <p>Documentation for Nqthm may be found in @(see bib::bm97).</p>

  <p>The Nqthm source code and proof scripts are available in two places,</p>

  @({
  ftp://ftp.cs.utexas.edu/pub/boyer/nqthm/nqthm-1992/
  })

  <p>and</p>

  @({
  https://drive.google.com/drive/folders/18z-uwg8E_3NxIijLoxYE-_NS-klqYI7R
  })

  <p>While it is possible to download individual files from these sites, we
  recommend that you download the entire @('nqthm-1992') distribution as
  follows.  In particular, download the gzipped tar file:</p>

  @({
  ftp://ftp.cs.utexas.edu/pub/boyer/nqthm/nqthm-2nd-edition.tar.gz
  })

  <p>to a directory where you want the Nqthm source code and regression
  suite, connect to that directory, and extract the files as follows.</p>

  @({
  tar xfz nqthm-2nd-edition.tar.gz
  })

  <p>That will create the directory @('nqthm-1992/').</p>

  <p>You do not have to build the Nqthm image or do a regression if all you
  want to do is inspect either the Nqthm source code (which consists of the
  files @('nqthm-1992/*.lisp')) or the files in the regression suite
  (@('nqthm-1992/examples/')).  You can just explore the relevant files
  locally.  If you want to build Nqthm and do a regression, see the Nqthm
  installation instructions in @('nqthm-1992/README').</p>

  <p>The ACL2 system, as it stood in 2000, is documented in two textbooks; see
  @(see pubs::pubs-books).  These books are a good place for a beginner to
  start, even though some of the material is out-of-date.  Up-to-date
  user-level @(see documentation) of ACL2 is available online as described in
  the User's Manuals link on the homepage (below), and a wealth of information
  is available there.  Some of it is organized for the experienced user trying
  to get information about a particular feature, but there is a documentation
  topic, @(see start-here), that provides many starting points for the
  beginning ACL2 user.</p>

  <p>Source code, input files, @(see installation) instructions, extensive
  online documentation and other material is available from the <a
  href='http://www.cs.utexas.edu/users/moore/acl2/'>ACL2 homepage</a>:</p>

  @({
  https://www.cs.utexas.edu/~moore/acl2/
  })

  <p>That page provides instructions for obtaining the latest ACL2 numbered
  release.  However, many ACL2 users obtain an up-to-date <a
  href='https://github.com/acl2/acl2'>snapshot of ACL2 from GitHub</a>:</p>

  @({
  https://github.com/acl2/acl2
  })

  <p>As with Nqthm, to explore ACL2 source files or prover input files we
  recommend that you see @(see installation) and follow the instructions there.
  That includes placing a copy of the latest sources and input scripts (but not
  prover output) in a directory on your computer.  The filenames suffixed with
  @('.lisp') at the top-level of that directory constitute the ACL2 source
  code.  The ACL2 regression suite consists of thousands of files called
  &ldquo;@(see books)&rdquo; and are available under the @('books/')
  subdirectory.  So, for example, you'll find a toy model of the JVM at
  @('books/models/jvm/m1/m1.lisp').  If you want to see proofs you must build
  ACL2 on your machine and run a full regression as described in the
  @(see installation) instructions.</p>

  <h3>Quick Index to Related Topics</h3>
  <ul>
  <li>@(see operational-semantics)</li>
  <li>@(see operational-semantics-1__simple-example)</li>
  <li>@(see operational-semantics-2__other-examples)</li>
  <li>@(see operational-semantics-3__annotated-bibliography)</li>
  <li>operational-semantics-4__how-to-find-things &mdash; current topic</li>
  <li>@(see operational-semantics-5__history-etc)</li>
  </ul>")
other
(defxdoc operational-semantics-5__history-etc
  :parents (operational-semantics)
  :short "A quick history of our style of modeling state machines"
  :long "<p>As informally explained in @(see operational-semantics) and
  illustrated in @(see operational-semantics-1__simple-example) and @(see
  operational-semantics-3__annotated-bibliography), the common ACL2 style in
  which state machines are modeled involves representing the relevant part of
  the state as an ACL2 object, defining a single-step function for computing
  state transitions, and then defining a total recursive run function for
  iterating the step function until it &ldquo;halts&rdquo; or some specified
  number of steps has been taken.</p>

  <p>This approach to operational semantics is different from &ldquo;structural
  operational semantics&rdquo; described by Plotkin in his 1981 paper &ldquo;A
  Structural Approach to Operational Semantics&rdquo; (see @(see
  bib::plotkin04a)).  Plotkin formalized machines operationally but as
  inference rules (reminiscent of Hoare logic).  See also @(see
  bib::plotkin04b), where Plotkin elaborates on the origins of that approach.
  Furthermore, the origins paper appears in a two volume special issue of
  <i>The Journal of Logic and Algebraic Programming</i> which contains many
  other papers on structural operational semantics.</p>

  <p>To distinguish the approach taken commonly in the ACL2 community from
  structural operational semantics we might call it &ldquo;ACL2-style&rdquo;
  operational semantics.  But its only connection to ACL2 is that ACL2 happens
  to be the logic in which our models are expressed.  Other settings supporting
  recursion and induction could also be used.  Boyer and Moore used this
  approach in the 1970s, inspired in part by McCarthy's seminal
  papers (&ldquo;Recursive Functions of Symbolic Expressions and Their
  Computation by Machine,&rdquo; 1960, &ldquo;A Basis for a Mathematical Theory
  of Computation,&rdquo; 1963, and &ldquo;Correctness of a Compiler for
  Arithmetic Expressions,&rdquo; with James Painter, 1967).  But we would be
  hard-pressed to attribute this style of operational semantics even to
  McCarthy.  In the first place, mathematicians have used formal state machines
  at least since since Goedel's 1931 incompleteness paper: he modeled proofs as
  objects (specifically, integers) and defined a non-terminating function that
  stepped through all possible proofs looking for a particular proof.  In the
  second place, machine designers and programmers have been writing software to
  emulate other machines for almost as long as computers have existed. ACL2 is
  just another programming language in which such software can be written
  &mdash; albeit one that comes with a logical foundation and theorem prover
  allowing one to reason about programs running on the machine or even
  properties of the machine itself.</p>

  <p>In fact, such operational semantics models played an important role in the
  evolution of ACL2.</p>

  <p>ACL2 evolved from earlier theorem provers by Boyer and Moore.  Those
  earlier provers were the Edinburgh Pure Lisp Theorem prover, aka PLTP (see
  @(see bib::bm73) and @(see bib::moore73)), (1971--73), Thm (1974--79), and
  Nqthm (1980--95) (see @(see bib::bm97)).  The dates are approximate.  Boyer
  and Moore began working on ACL2 on August 14, 1989 and the first ACL2
  proof (associativity of @('append')) was done on November 3, 1989.  Matt
  Kaufmann officially joined the ACL2 development team in August, 1993,
  although he had become an invaluable contributor years before that.  See
  &ldquo;@('; Commemorative Plaque')&rdquo; in the ACL2 source file
  @('prove.lisp').  For a description of the evolution from PLTP, through Thm,
  and Nqthm, to ACL2, including proper bibliographic citations, see @(see
  bib::moore19).</p>

  <p>Boyer and Moore's first foray into operational semantics for a computing
  machine shows up in Chapter 17 of @(see bib::bm79) where they used Thm to
  prove a version of the McCarthy-Painter theorem verifying an expression
  compiler for a simple machine @(see bib::mp67).</p>

  <p>At the time, Boyer and Moore were employed at SRI and were working
  part-time on the Software Implemented Fault Tolerance (SIFT) project.  Their
  task was to verify that a certain small fragment of machine code for the
  Bendix 930 (BDX930) flight-control computer implemented a simple time-sharing
  system.  (Personal aside by J Moore: Having such an ambitious goal, in 1979,
  astounds me in 2024, but it was a side-effect of youthful energy combined
  with naivete and the excitement (and hype?) of that early period in the
  history of mechanized formal methods.)  To attack the problem they formalized
  the necessary subset of the BDX930 instruction set operationally.  But Thm
  was not able to process the &ldquo;large&rdquo; system of definitions (30
  pages).  The problem was, in part, due to the representation of logical
  constants in Thm's implementation.  E.g., the logical constant @('1') was
  represented as the ground term @('(add1 (zero))'), and the logical constant
  pair containing @('1') in its @('car') and @('2') in its @('cdr') was the
  ground term:</p>

  <code>
  (cons (add1 (zero)) (add1 (add1 (zero))))
  </code>

  <p>So Thm was rewritten to represent the constant @('1') as @('(quote 1)')
  and the constant pair above as</p>

  <code>
  (quote (1 . 2)).
  </code>

  <p>This required a major rewrite (affecting virtually every routine in the
  system that inspected terms) and was a significant step toward Nqthm.  (Note:
  another formalization problem pushed Boyer and Moore in the same direction:
  the desire to support verified &ldquo;metafunctions,&rdquo; which required
  the formalization in the logic of a weak interpreter, @('V&C$'), for the
  logic.)</p>

  <p>The BDX930 model was admitted to the improved &ldquo;Thm&rdquo; (now more
  like Nqthm) but Boyer and Moore then realized that the machine code
  implemented a time-sharing system only if every SIFT process, when compiled
  from the native Pascal, respected a bevy of unstated invariants on the
  machine code.  They wrote a &ldquo;minority report&rdquo; explaining this.
  That report was contained in Sections 14 and 15 of the SIFT final report for
  the period September 1978 to June 1982.  Section 14 describes the problem and
  Section 15 lists the 30 page BDX930 model.  See @(see bib::bm80), which has
  the provocative title &ldquo;WHY IT IS IMPOSSIBLE TO PROVE THAT THE BDX930
  DISPATCHER IMPLEMENTS A TIME-SHARING SYSTEM.&rdquo;</p>

  <p>Boyer and Moore left SRI for the University of Texas at Austin in 1981 and
  Nqthm was fully formed shortly thereafter.  The combination of Nqthm and some
  brilliant students led to a remarkable string of projects, including the
  FM8501 (and later the FM9001), the Computational Logic, Inc., verified stack,
  and the Motorola 68020 model and its use in the emulation and verification of
  machine code produced from the Berkeley C String Library by @('gcc -o').
  (See @(see operational-semantics-3__annotated-bibliography) for proper
  citations.)  These projects pushed Nqthm to its limits: models were large and
  running them as software prototypes of the compute engines they modeled was
  relatively slow.</p>

  <p>That spurred Boyer and Moore to abandon the home grown Lisp supported by
  Nqthm and build a theorem prover for a subset of Common Lisp: ACL2.  That
  way, operational models were just Common Lisp functions and could be run at
  Common Lisp speeds.</p>

  <p>Of course, pressure on Kaufmann and Moore to improve ACL2 to provide
  higher capacity and more efficiency to load and process models of commercial
  processors continues to this day.  See Sections 8 and 9 of @(see
  bib::hkms17).  Among many other changes made in response to industrial
  requests, many of which relate to operational models, are such things the
  invention of guards as an extralogical device to ensure that compiled code
  complies with the axioms, support for inlining and other directives to the
  compiler, the @(tsee mbt) directive, performance improvements in
  certification and the inclusion of certified files into a session, congruent
  single-threaded objects, nested single-threaded objects, patterned congruence
  rules, and an attachment mechanism for stobjs so that different memory models
  can be executed.  See @(see stobj)s.</p>

  <h3>Quick Index to Related Topics</h3>
  <ul>
  <li>@(see operational-semantics)</li>
  <li>@(see operational-semantics-1__simple-example)</li>
  <li>@(see operational-semantics-2__other-examples)</li>
  <li>@(see operational-semantics-3__annotated-bibliography)</li>
  <li>@(see operational-semantics-4__how-to-find-things)</li>
  <li>operational-semantics-5__history-etc &mdash; current topic</li>
  </ul>")
other
(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)")
other
(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>")
other
(defxdoc otf-flg
  :parents (defthm thm xargs)
  :short "Allow more than one initial subgoal to be pushed for induction"
  :long "<p>This keyword argument for certain @(see events) controls whether
 the theorem prover will abandon its initial work upon encountering the second
 subgoal to push for proof by induction: @(':otf-flg') is @('nil') for that
 behavior, but @('t') if it should instead continue &ldquo;Onward Through the
 Fog&rdquo; and complete @(see waterfall) processing before starting any proof
 by induction.</p>

 <p>The default value for @(':otf-flg') is @('nil') except during processing of
 @(tsee defun) events, where the default is @('t') for both termination and
 @(see guard) proofs (see @(see defun)).  Note that the default for
 @(':otf-flg') is thus @('t') for processing @(tsee verify-termination) events,
 since they abbreviate @('defun') events.  However, the default for
 @(':otf-flg') is @('nil') for processing @(tsee verify-guards) events.</p>

 <h3>Further Explanation</h3>

 <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>")
other
(defxdoc output-controls
  :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>")
other
(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)
 })")
other
(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>")
other
(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>")
other
(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 (but see
 @(see allegro-cl) for a caveat about Allegro Common Lisp):</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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>

 <p>If you are actually in a break caused by @(see break-rewrite), @(':p!') and
 @('(p!)') just print a message and otherwise are no-ops.  (A comment in the
 source code definition of @('p!') explains why break-rewrite cannot support
 ``popping up one level'' in the sense that you would probably expect.)</p>")
other
(defxdoc packages-for-generated-symbols
  :parents (packages)
  :short "Convention for packages of generated symbols"
  :long "<p>ACL2 utilities, whether defined in the ACL2 sources or in books,
 will ideally provide the following default behavior when feasible: generated
 symbols should be in the @(tsee current-package).  This is the ACL2 version of
 the general principle enforced by almost all programming languages: names
 introduced are, by default, in the current namespace.  We do not claim that
 ACL2 currently adheres to this principle in all cases, but our hope that this
 situation is improved over time.  Indeed, the utilities @(tsee defequiv),
 @(tsee defrefinement) and @(tsee defcong) have been improved to conform to
 this principle; see @(see note-8-3).  We hope that future utilities, not only
 in ACL2 but also in the @(see community-books), will respect this principle
 when feasible.  Conforming to this principle requires using @(tsee make-event)
 in a top level form to determine the @(tsee current-package) from @(tsee
 state) and then passing this package to functions that generate symbols.  The
 section @('Symbol generation utilities') of ACL2 source file @('defthm.lisp')
 contains utilities that are useful for generating symbols.  The code was
 adapted from similar code in @(tsee ACL2s); see the community book
 @('acl2s/utilities.lisp') which includes even more such utilities.  To see an
 example of a utility that generates symbols in the current package, see
 @('books/acl2s/defunc.lisp'), which contains the @(tsee acl2s::defunc)
 utility.  Other examples include @(tsee defequiv), @(tsee defrefinement) and
 @(tsee defcong) in @('defthm.lisp').</p>")
other
(defxdoc package-reincarnation-import-restrictions
  :parents (packages)
  :short "Re-defining undone @(tsee defpkg)s"
  :long "<p>ACL2 imposes the following restriction on redefining packages.
 Note that for the notion of a package definition being &ldquo;undone&rdquo;,
 the undoing might have been by use of @(':')@(tsee ubt), or it might have been
 because the @('defpkg') form was evaluated by a @(see local) event that
 disappeared during the second pass of an @(tsee encapsulate) or @(tsee
 include-book) event.</p>

 <blockquote>

 Suppose @('(defpkg "pkg" imports)') has been evaluated successfully and then
 has been undone.  Then any future attempt in the same session to define
 @('"pkg"') as a package must specify an identical imports list.

 </blockquote>

 <h3>Reasons for the restriction</h3>

 <p>We will see below that the restriction above is necessary for avoiding
 unsoundness.  But first consider the following simple example, which shows
 that the package doesn't entirely disappear when undone.</p>

 @({
 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 !>(assign x 'foo::a)
  FOO::A
 ACL2 !>(u) ; undoes the defpkg event
            0:x(EXIT-BOOT-STRAP-MODE)
 ACL2 !>(@ x)
 FOO::A
 ACL2 !>(eq (@ x) 'acl2::a)
 NIL
 ACL2 !>
 })

 <p>Suppose that (without the restriction) the package @('"FOO"') can now be
 introduced as @('(defpkg "FOO" '(a))').  Then will @('(eq (@ x) 'acl2::a)')
 evaluate to @('nil') as before, since we didn't make another assignment to
 @('x')?  Or would that equality evaluate to @('t') since the only symbol in
 package @('"FOO"') whose @(tsee symbol-name) is @('"A"') is @('acl2::a')?
 Each result is plausible so to avoid confusion, it might be best if @('(@ x)')
 is now undefined.  But that would require somehow removing all symbols in the
 @(see state) whose package is @('"FOO"') when undoing the @('defpkg') event,
 which can be inefficient and &mdash; more importantly &mdash; may not make
 sense if there are @(see stobj)s that include such symbols.  What a mess!</p>

 <p>A more important reason for the restriction is that it prevents
 unsoundness.  Consider the following two books.</p>

 @({
 ;;; book1.lisp
 ;;; Portcullis command: (defpkg "FOO" '())
 (in-package "ACL2")
 (defthm thm1
   (equal (symbol-package-name (intern$ "A" "FOO"))
          "FOO"))

 ;;;;;;

 ;;; book2.lisp
 ;;; Portcullis command: (defpkg "FOO" '(a))
 (in-package "ACL2")
 (defthm thm2
   (equal (symbol-package-name (intern$ "A" "FOO"))
          "ACL2"))
 })

 <p>After each of these two books is certifiable in a (separate) fresh ACL2
 session, consider the following two events.</p>

 @({
 (encapsulate
   ()
   (local (include-book "book1"))
   (defthm thm1
     (equal (symbol-package-name (intern$ "A" "FOO"))
            "FOO")))

 (encapsulate
   ()
   (local (include-book "book2"))
   (defthm thm1
     (equal (symbol-package-name (intern$ "A" "FOO"))
            "ACL2")))
 })

 <p>Each is accepted in a separate, fresh ACL2 session.  But if we could admit
 the first and then the second in the same session, we could of course prove
 @('nil').  Fortunately, if we try that, then ACL2 implements the restriction
 by complaining about the second as follows, when encountering the @('(local
 (include-book "book2"))') form in the second @('encapsulate').</p>

 @({
 ACL2 Error in ACL2-INTERFACE:
 We cannot reincarnate the package "FOO" because it was previously defined
 with a different list of imported symbols.
 })

 <p>A final reason for the restriction stems from 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.  So because of saved @(see world)s, we do not
 clear out a package when it is undone.</p>

 <h3>A logical view of the restriction</h3>

 <p>The restriction on redefining packages is based on the following part of
 the logical foundation of ACL2.</p>

 <blockquote>

 <b>Logical Persistence of Packages.</b><br/>

 When a package is introduced by @(tsee defpkg) in an ACL2 session, its
 definition is considered to persist logically even if that @(see defpkg) @(see
 event) is undone.

 </blockquote>

 <p>That principle certainly rules out the new definition of an undone package
 with different imports.  It also explains why package definitions from @(see
 local)ly included @(see books) are included in a book's @(see portcullis)
 commands; see @(see hidden-defpkg).  Note that this is a <i>logical</i>
 principle; if you undo a @(tsee defpkg) event, then ACL2 will prevent you from
 referencing that package explicitly unless you first reintroduce it &mdash;
 with the same imports, because of the restriction.</p>")
other
(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.")
other
(defxdoc packn
  :parents (symbols acl2-built-ins)
  :short "Build a symbol from a list"
  :long "<p>The call @('(packn lst)') returns a symbol whose name is a
 concatenation of string representations of the atoms in the @(tsee
 atom-listp), @('lst').  The symbol's package is the package of the first
 symbol in @('lst') whose package is not @('"COMMON-LISP"') if any, else
 @('"ACL2"').</p>")
other
(defxdoc packn-pos
  :parents (symbols acl2-built-ins)
  :short "Build a symbol in a specified package from a list"
  :long "<p>The function @('packn-pos') behaves like @(tsee packn), except that
 for the call @('(packn-pos lst witness)'), the returned symbol's package will
 instead be the package of the symbol, @('witness').</p>")
other
(defxdoc pairlis
  :parents (lists alists)
  :short "See @(see pairlis$)"
  :long "<p>The Common Lisp language allows its @('pairlis') function to
 construct an alist without specifying a single order!  So we have to define
 our own version: See @(see pairlis$).</p>")
other
(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$)")
other
(defxdoc pairlis-x1
  :parents (lists alists acl2-built-ins)
  :short "Cons a given element to each member of a list"
  :long "<p>The call @('(pairlis-x1 x1 lst)') conses @('x1') onto each element
 of the true-list, @('lst').</p>")
other
(defxdoc pairlis-x2
  :parents (lists alists acl2-built-ins)
  :short "Cons each element of a list with a given element"
  :long "<p>The call @('(pairlis-x2 lst x2)') creates an alist consing each
 element of @('lst'), a true-list, with @('x2').</p>")
other
(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>")
other
(defxdoc parallel
  :parents (parallelism)
  :short "Evaluating forms in parallel"
  :long "<p>See @(see parallelism).</p>")
other
(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>")
other
(defxdoc parallel-programming
  :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>")
other
(defxdoc parallel-proof
  :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>")
other
(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>")
other
(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>")
other
(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>")
other
(defxdoc parallelism-build
  :parents (parallelism)
  :short "Building an ACL2 executable with parallel execution enabled"
  :long "<p>See @(see compiling-acl2p).</p>")
other
(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)))
 })")
other
(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>")
other
(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>")
other
(defxdoc partial-encapsulate
  :parents (events encapsulate)
  :short "Introduce functions with some constraints unspecified"
  :long "<p>See @(see encapsulate) for relevant background.
 @('Partial-encapsulate') is a variant of @('encapsulate') for which some of
 the constraints are implicit.  This is an advanced capability that is useful
 when one installs special-purpose code, possibly in raw Lisp, using a trust
 tag (see @(see defttag)).</p>

 <h3>Introduction</h3>

 <p>The syntax for @('partial-encapsulate') is the same as the syntax of
 @('encapsulate'), except for the addition of an argument, @('supporters'),
 which is described below.</p>

 @({
  General Form:
  (partial-encapsulate (signature ... signature)
    (f1 ... fk) ; supporters
    ev1
    ...
    evn)
 })

 <p>where, as for @('encapsulate'): each @('signature') is a well-formed @(see
 signature), each describing a different function symbol, and each @('evi') is
 an embedded event form (see @(see embedded-event-form)).  The additional
 argument (shown above) is a true-list of function symbols, the
 <i>supporters</i>: it is an error if any such symbol, @('fi'), is not a known
 function symbol at the time the @('partial-encapsulate') call is evaluated,
 the exception being that @('fi') may be introduced in one of the signatures.
 A @('partial-encapsulate') form must satisfy the following three requirements
 in addition to those of the corresponding @('encapsulate') form: it must have
 at least one signature, it must not occur within any other @('encapsulate') or
 @('partial-encapsulate') form that has at least one signature, and every
 function symbol that it introduces must be specified in one of the
 signatures.</p>

 <p>A call of @('partial-encapsulate') introduces its signature functions
 together with its exported theorems, exactly as though it had been the call of
 @('encapsulate') with the same signatures and events, however with one
 difference: the @('partial-encapsulate') logically incorporates additional
 constraints that are not mentioned.  This is discussed further below, but for
 now let us note that because of this difference, a successful evaluation of a
 @('partial-encapsulate') form results in a special ``unknown-constraints''
 designation for the functions introduced by the signatures.  Any attempt to
 access the constraints for those functions will thus fail.  Consider the
 following example, which introduces @('f') as a constrained function symbol
 that is constrained not only by the property that @('f') returns a boolean,
 but also by additional, unspecified (implicit) constraints.</p>

 @({
 (partial-encapsulate
  ((f (x) t))
  nil
  (local (defun f (x) (declare (xargs :guard t)) (consp x)))
  (defthm booleanp-f
    (booleanp (f x))
    :rule-classes :type-prescription))

 (defthm symbolp-f
   (symbolp (f y)))

 (encapsulate
  ((g (x) t))
  (local (defun g (x) (consp x)))
  (defthm booleanp-g (booleanp (g x))))

 })

 <p>Then the following fails, even though it would succeed if we replace
 @('partial-encapsulate') by @('encapsulate') above.  The reason is that the
 partial-encapsulate form allows for constraints beyond just the property that
 @('f') is boolean.  Imagine that special code had been inserted (using a trust
 tag) for reasoning about @('f') when proving a theorem like @('symbolp-f')
 that we were now trying to functionally instantiate.</p>

 @({
 ; Functional instantiation FAILS because of unknown-constraints on f
 (defthm symbolp-g
   (symbolp (g y))
   :hints (("Goal" :by (:functional-instance symbolp-f (f g)))))
 })

 <h3>Supporters and corresponding encapsulate</h3>

 <p>A @('partial-encapsulate') represents any @('encapsulate') form that
 introduces the same function symbols, has the same signatures, and extends the
 constraints introduced such that every function symbol occurring in at least
 one of the additional constraints must either be mentioned in one of the
 @('evi') or be among the list of supporters, @('(f1 ... fk)').  We may refer
 to such an @('encapsulate') form as a ``corresponding encapsulate''.  The user
 of @('partial-encapsulate') should keep in mind such a set of additional
 constraints.  The supporters should thus include all function symbols in the
 theorems exported from the intended corresponding encapsulate, except that
 signature functions are always included among the supporters whether specified
 or not, and hence their inclusion is optional.</p>

 <p>The list of supporters is used for generating proof obligations for a
 @(':functional-instance') @(see lemma-instance).  Specifically, the supporters
 serve as the ``ancestors'' of the partial encapsulate's signature functions,
 in the constraint-generation algorithm described in the documentation for
 @(see constraint).  Thus, if supporters are missing that occur in the intended
 corresponding encapsulate, then functional instantiation may be unsound
 because some proof obligations fail to be generated.  Note that in the typical
 application described next, where the implicit constraints all specify
 evaluation results for calls of signature functions as discussed below, the
 specified list of supporters can simply be @('nil').</p>

 <h3>Applications</h3>

 <p>A trust tag (see @(see defttag)) is not needed for evaluation of a
 partial-encapsulate form.  However, for a typical application of
 partial-encapsulate &mdash; redefinition of a constrained function in raw Lisp
 &mdash; a trust tag is of course necessary (see @(see defttag)).  In such a
 case, the corresponding encapsulate may be viewed as extending the original
 partial-encapsulate with all theorems of the form @('(equal (f a1 ... ak)
 val)'), ranging over all computations @('(f a1 ... ak)') ever to be
 evaluated (a finite but potentially huge set) where @('val') is the value
 returned for @('(f a1 ... ak)').  It is the responsibility of the creator of
 such an application to ensure that all evaluations satisfy the original
 constraints of the partial-encapsulate.</p>

 <p>Note that in this sort of application &mdash; that is, where the implicit
 constraints all arise from function evaluations &mdash; the supporters
 argument may soundly be @('nil'), since only the signature functions are
 involved in the implicit constraints (and those functions are automatically
 included among the supporters, even when not specified by the user).</p>

 <p>For examples of such an application, including explanatory comments, see
 @(see community-books) and @('books/demos/partial-encapsulate.lisp') and
 @('books/demos/include-raw-examples/mem-access-sound/mem.lisp').</p>

 <p>Partial-encapsulates are, in essence, also used in the implementation of
 dependent clause-processors, where the list of supporters might well be
 non-@('nil').  See @(see define-trusted-clause-processor).</p>

 <h3>Implementation</h3>

 <p>This section is provided as a reference for those interested, but can
 probably be safely skipped by most readers.</p>

 <p>Consider the following example.</p>

 @({
 ACL2 !>:trans1 (partial-encapsulate
                 ((f0 (x) t))
                 (g0)
                 (local (defun f0 (x) x))
                 (defthm f0-prop
                   (implies (integerp x)
                            (integerp (f0 x)))))
  (ENCAPSULATE ((F0 (X) T))
               (LOCAL (DEFUN F0 (X) X))
               (DEFTHM F0-PROP
                       (IMPLIES (INTEGERP X)
                                (INTEGERP (F0 X))))
               (SET-UNKNOWN-CONSTRAINTS-SUPPORTERS G0))
 ACL2 !>
 })

 <p>This example illustrates that a @('partial-encapsulate') call expands to a
 call of @('encapsulate') obtained by removing the supporters argument, but
 with the following extra event inserted after given list of events, where
 @('(f1 ... fk)') is the specified list of supporters.</p>

 @({
 (set-unknown-constraints-supporters f1 ... fk)
 })

 <p>The macro, @('set-unknown-constraints-supporters'), extends a table,
 @('unknown-constraints-table').  As evaluation of the partial-encapsulate
 concludes, the world is extended so that each signature function has a
 @(''constraint-lst-etc') property indicating that its constraints are unknown,
 but with supporters (``ancestors'', as discussed above) according to that
 table.  This macro call can thus be inserted non-@(see local)ly within an
 encapsulate, anywhere after the local function definitions, to make an
 encapsulate behave like a partial-encapsulate.</p>")
other
(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)
 for how relative pathnames are elaborated to absolute pathnames.  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>")
other
(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 @(see 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 or in @(see
 proof-builder) commands such as @('=') and @('equiv').  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>")
other
(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>")
other
(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)
 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 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 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 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>")
other
(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>")
other
(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>")
other
(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>")
other
(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.  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>See @(see pc) for a description of the format used to display a @(see
 command).</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>")
other
(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>")
other
(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
  :pf (:induction foo) ; prints the induction scheme associated with foo
 })

 <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.  If the argument names an @(':')@(tsee
 induction) rule, then the corresponding induction scheme is printed.</p>")
other
(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 COMMON-LISP::CAR)).
 })

 <p>Then @('(pkg-imports "MY-PKG")') equals the list @('(ACL2::ABC
 COMMON-LISP::CAR)').  Note that @('COMMON-LISP::CAR') is the same as
 @('ACL2::CAR'), which is printed as just @('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
 })")
other
(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>")
other
(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 quote      ; prints rules that rewrite quoted constants
  :pl (+ x y)    ; prints rules that rewrite (+ x y)
  :pl '(4 1 2 3) ; prints rules that rewrite '(4 1 2 3)
 })

 <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 the symbol
 @('quote'), 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.  When the argument to @('pl') is @('quote'), @('pl') displays
 the rules that rewrite quoted constants, i.e., the @(':')@(tsee
 rewrite-quoted-constant) rules.  Otherwise, @(':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).  For each
 class, rules are displayed in order from the most recently submitted rule to
 the oldest, with two exceptions: @(':rewrite'), @(':definition'), and
 @(':meta') rules are considered as one ``class'' for this purpose; and only
 the current (most recent) @(':elim') rule is displayed.</p>

 <p>Otherwise the argument should be a term.  Note that the term may have
 user-level syntax (that is, it may be an untranslated term; see @(see term)),
 for example one that is obtained from the theorem prover's output; in
 particular, macro calls are permitted.  When supplied a term, @(':pl')
 displays rules that are (possibly) applicable to the given term, in order (as
 above, most recent rule first) for each of these four cases: first
 @(':')@(tsee rewrite-quoted-constant), @(':')@(tsee rewrite) and @(':')@(tsee
 definition) rules, then @(':meta') rules, then @(':')@(tsee linear) rules, and
 finally @(':')@(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.  (Those techniques include @(see type-reasoning), @(see
 forward-chaining), and some attempts to deal with @(see free-variables)
 including handling of binding hypotheses, @(tsee syntaxp) and @(tsee
 bind-free).)</p>

 <p>It is important to remember that rules displayed as ``applicable'' by
 @('pl') may in fact not be used because of logical requirements, like
 failure to relieve the hypotheses in the context in which the target occurs,
 or because of heuristics such as those controlled by the @(':')@(tsee
 loop-stopper).</p>

 <p>A reminder of this can sometimes be seen in the output of @('pl').  For
 example, if the list of un-discharged hypotheses contains @('nil') then the
 hypotheses of this instance the rule are known, by trivial means, to be
 unsatisfiable.</p>

 <p>Similarly, @(':')@(tsee rewrite-quoted-constant) rules of form @('[2]') are
 not actually applied unless a certain computation produces a quoted constant.
 For example,</p>

 @({
 ACL2 !>(include-book "demos/rewrite-quoted-constant-examples" :dir :system)
 })

 <p>includes a form @('[2]') rule, named @('form-2-rule'), which will rewrite
 any quoted constant occurring a position admitting @('set-equalp') as a
 congruence.  The rule will apply the function @('drop-dups-and-sort') to the
 constant and replace the constant by the result &mdash; if the result is a
 quoted constant.  That function coerces the constant to a @(tsee true-listp),
 drops duplicate elements, and sorts the list.  Thus, @(''(3 1 1 2 . 77)') in a
 @('set-equalp') occurrence would be rewritten to @(''(1 2 3)').  However, that
 replacement is only made if @('(drop-dups-and-sort '(3 1 1 2 . 77))') is
 rewritten to a quoted constant.</p>

 @({
 ACL2 !>:pl '(3 1 1 2 . 77)
 })

 <p>will include an entry for @('form-2-rule'), but the entry reads:</p>

 @({
  New term: (DROP-DUPS-AND-SORT '(3 1 1 2 . 77))
  Hypotheses: <none>
  Equiv: SET-EQUALP
  Substitution: ((LST '(3 1 1 2 . 77)))
  WARNING:  The new term above is only used if it rewrites to a quoted
  constant!
 })

 <p>How might the replacement not be made?  One way is if
 @('drop-dups-and-sort') and its @(tsee executable-counterpart) are both
 disabled and there are no @(':rewrite') rules about that function.</p>

 <p>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-cl-proc-table)'); see @(see clause-processor) and see @(see
 define-trusted-clause-processor).</p>")
other
(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>")
other
(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>")
other
(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)")
other
(defxdoc pointers
  :parents (documentation)
  :short "Links pointing to relevant documentation topics")
other
(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>")
other
(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 book 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 contribute
 to 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.  Note that when
 @('include-book') evaluates portcullis commands, it skips proofs and ignores
 @(see local) events.</p>

 <p>Clearly, a book is most useful if its certification takes place with as few
 non-@(see local) events as possible that extend the initial logical @(see
 world).  If, for example, your certification @(see world) happens to contain a
 @(tsee defpkg) for @('"MY-PKG"') and a non-local definition of a 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>")
other
(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)")
other
(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)
 @(def position-equal)
 @(def position-equal-ac)
 @(def position-ac)")
other
(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)")
other
(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>")
other
(defxdoc ppr-special-syms
  :parents (io)
  :short "A @(see table) to control indentation for pretty-printing"
  :long "<p>ACL2 output is generally pretty-printed: that is, spacing and
 indentation are controlled to enhance readability and aesthetics of the
 output.  Indentation may be controlled by using the table,
 @('ppr-special-syms') as described below.  We thank Stephen Westfold for
 enhancing the pretty-printer with support for @('ppr-special-syms').</p>

 <p>The initial value of the @('ppr-special-syms') table is given by the
 constant @('*ppr-special-syms*') as follows.  It associates each key, a symbol,
 with a corresponding <i>special-term-num</i> as discussed below.</p>

 @(def *ppr-special-syms*)

 <p>The @('ppr-special-syms') table is extended for some common macros in the
 files where they are defined, for example for @(tsee define) and @(tsee
 b*).</p>

 <p>For calls of special forms and macros in the @('ppr-special-syms') table,
 their bodies are indented by 2 rather than in the usual default manner.  To
 support this we allow a <i>special-term-num</i> to be associated with a
 symbol.  Arguments of such symbols in the function position beyond the
 special-term-num position are indented by 2.  Earlier arguments are printed
 normally.  For example, the symbol, @('let'), has a special-term-num of 1, so
 the first argument is printed normally and subsequent arguments are indented
 by 2, as follows.</p>

 @({
 (LET ((A B)
       (C D))
   (F A C))
 })

 <p>Since `if' has a special-term-num of 2, the first two arguments are printed
 normally and the other is indented by 2, for example as follows.</p>

 @({
 (IF (P A B)
     (F A B)
   (G A B))
 })

 <p>Macros often have as their first argument a symbol, so these are treated
 specially by putting them on the first line and any remaining arguments before
 the body arguments begin on the same line if there is space.  For example,
 @('defun') has special-term-num 2, which is evident in the following
 output.</p>

 @({
 (DEFUN FOO (X Y Z)
   (F X Y Z))
 })

 <p>Keyword pairs in macro calls can occur in other places than at the end of
 an argument list, so keyword pairing is done more aggressively, as in the
 following output.</p>

 @({
 (DEFINE FOO ((X P1)
              (Y P2))
   :GUARD (P3 X Y)
   (F X Y Z))
 })")
other
(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)))
 })")
other
(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 @(see congruence) rules, @(see
 equivalence) rules, or @(see refinement) rules.  Moreover, @(see induction)
 rules that are created by recursive definitions will not show up with
 @(':pr').</p>

 <p>The expert user might also wish to use @(tsee find-rules-of-rune).  See
 @(see find-rules-of-rune).</p>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>The one weakness of the rule above is that it only rewrites @('(member
 x (nats-below y))') when an instance of that target term occurs in a
 propositional setting, e.g., when the governing equivalence relation is
 @('iff').  But, thanks to Andrei Koltsov, an even stronger version is
 available as an unconditional @('equal')ity rewrite:</p>

 @({
 (defthm member-nats-below-stronger
   (equal (member x (nats-below y))
          (if (natp x)
              (if (natp y)
                  (if (<= x y)
                      (nats-below x)
                      nil)
                  (if (= x 0) '(0) nil))
              nil)))
 })

 <p>The key observation is that when @('x') and @('y') are both naturals and
 @('(<= x y)'), the result that @('member') computes can be expressed with
 @('nats-below').  You may wonder whether this stronger rule allows the
 immediate proof of the earlier @('member-nats-below-strong') and the answer is
 yes, because from the definition of @('nats-below') ACL2 has observed that
 @('(nats-below x)') is a @('cons') whenever @('x') is a natural.</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>")
other
(defxdoc pre-built-binary-distributions
  :parents (about-acl2)
  :short "Pre-built binary distributions of ACL2"
  :long "<p>Visit the &ldquo;Recent changes to this page&rdquo; link on the <a
 href='http://www.cs.utexas.edu/users/moore/acl2/'>ACL2 home page</a> to see if
 there are other shortcuts available.</p>

 <p><font color='red'><b>WARNING</b></font>: Some of these packages might
 be for old versions of ACL2.  We recommend that you use the latest
 version of ACL2 (Version 8.6).</p>

 <h3>Linux/Mac/Windows Binaries in ACL2s</h3>

 <p>The ACL2 Sedan (see @(see acl2-sedan)), also known as ACL2s, is an
 Eclipse-based IDE for ACL2 that is distributed with pre-certified books and
 pre-built binaries, though it is not always based on the latest ACL2 version.
 The ACL2 Sedan is distributed via a Homebrew package for Linux and macOS
 users, and as a Windows Subsystem for Linux distro for Windows users.</p>

 <p>See @(see acl2s::acl2s-installation) for instructions for installing the
 ACL2 Sedan. Note that these instructions are typically intended for students
 at Northeastern, but hopefully are useful for anyone interested in installing
 ACL2s.</p>

 <h3>Windows</h3>

 <p>In the past, a Windows Installer for ACL2 has included a Unix environment,
 pre-certified standard and workshop books, and a copy of Gnu Emacs.  This
 capability has largely been superseded; see @(see windows-installation).</p>

 <h3>macOS</h3>

 <p>ACL2 versions are sometimes been made available <a
 href='https://ports.macports.org/port/acl2/'>under MacPorts</a>.</p>

 <p>Some folks maintain <a href='https://formulae.brew.sh/formula/acl2'>a
 Homebrew package</a> that tracks the latest stable version of ACL2.</p>

 <h3>Debian GNU Linux</h3>

 <p>A Debian Gnu Linux package is available, which is likely to work on other
 Linux systems as well.  Thanks to Camm Maguire for maintaining this package,
 and for pointing out that as Debian packages are simply @('ar') and @('tar')
 archives, they can be unpacked on any linux system, and who has said:
 &ldquo;If someone is running Debian, all they want to do is 'apt-get install
 acl2', doing likewise for any optional add-on package they wish as well,
 e.g. emacs, infix, etc.&rdquo; Alternatively, Debian GNU Linux users may wish
 to <a href='http://packages.qa.debian.org/a/acl2.html'>download the ACL2
 Debian package for Linux</a>.  An alternate location you might want to check
 is <a href='http://backports.debian.org'>@('backports.debian.org')</a>.</p>

 <h3>Docker images</h3>

 <p>Some folks maintain Docker images for ACL2. Below is a nonexhaustive list
 of such images; feel free to add to this list. DH refers to Docker Hub and
 GHCR refers to the GitHub Container Registry.</p>

 <ul>
 <li>DH: <a href='https://hub.docker.com/r/atwalter/acl2/'>atwalter/acl2</a>, GHCR: <a href='https://github.com/mister-walter/acl2-docker/pkgs/container/acl2'>mister-walter/acl2</a></li>
 <li>DH: <a href='https://hub.docker.com/r/atwalter/acl2s/'>atwalter/acl2s</a>, GHCR: <a href='https://github.com/mister-walter/acl2s-docker/pkgs/container/acl2s'>mister-walter/acl2s</a></li>
 </ul>

 ")
other
(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*)")
other
(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>")
other
(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)")
other
(defxdoc print-cl-cache
  :parents (apply$)
  :short "Information about the cache supporting @('apply$')"
  :long "<code>
  General Form:
  (print-cl-cache)
  </code>

  <p>Logically this function always returns @('NIL') but it prints to the
  comment window information about the cache that supports the application of
  quoted @('LAMBDA') objects by @(tsee apply$).  The name stands for Print
  Compiled Lambda Cache.</p>

  <p>In general there is a non-empty cache line for each @('LAMBDA') object
  used in a @('defun') or seen by @('verify-guards') or by @('apply$') in the
  evaluation theory.  But the cache has a maximal size.  If a new @('LAMBDA')
  object is seen when the cache is full, the least recently used line is
  re-used for the new @('LAMBDA') object.  By default the maximal cache size is
  1000.  This can be changed -- with the side-effect of clearing the cache --
  by exiting the ACL2 loop with @(':q') and doing @('(setq *cl-cache* k)'),
  where @('k') is the new maximal size.</p>

  <p>When @('print-cl-cache') is called it prints a block about each non-empty
  cache line enumerated from 0, and listed in the order that the cache is
  searched when a @('LAMBDA') object is @('apply$')d.  Each block contains:</p>

  <ul>
  <li>@(':lambda-object') - a fully translated @('LAMBDA') object</li>

  <li>@(':status') - one of four keywords with the following meanings:
      <ul>

      <li>@(':GOOD') - the @('LAMBDA') object is well-formed and Common Lisp
          compliant (``guard verified'') in the current world</li>

      <li>@(':BAD') - the @('LAMBDA') object is not well-formed or not Common
          Lisp compliant (``guard verified'') in the current world, but
          (with high probability) there is a world in which it is well-formed
          and compliant</li>

      <li>@(':UGLY') - the @('LAMBDA') object is so ill-formed it can never be
          @(':GOOD') in any world, e.g., @('(LAMBDA (T) (CONS 3 . 4))')</li>

      <li>@(':UNKNOWN') - we do not know the status of this object in the
          current world and leave it to @('apply$') to determine the proper
          status the next time this object is @('apply$')d.</li>

      </ul>
     </li>
  <li>@(':abs-event-no') - the absolute event number (in the current world) at
      which the @('LAMBDA') object was proved to have status @(':GOOD'), or
      @('NIL') if its status is not @(':GOOD')</li>

  <li>@(':extracts') - some parts of the @('LAMBDA') object sufficient to
      confirm well-formedness.  Well-formedness must be re-confirmed if the
      world is retracted to before the object became @(':GOOD')</li>

  <li>@(':problem') - One of the following values.
      <ul>
      <li>@('NIL') - no problem; status is @(':GOOD')</li>

      <li>@('NOT-WELL-FORMED') - the @('LAMBDA') is syntactically plausible but
          not well-formed but could, perhaps, become well-formed in a suitable
          extension of the current world, e.g., the body calls an undefined
          function (but perhaps it can be defined), the body contains a
          @(':program') mode function (but perhaps that could be upgraded to
          @(':logic') mode), the body contains an unbadged or unwarranted
          function symbol (but perhaps @('defbadge') or @('defwarrant') could
          resolve the issue), etc.</li>

      <li>@('(GUARD-USES-NON-COMPLIANT-FNS . fns)') - @('fns') is a list of
          function symbols used in the guard of the @('LAMBDA') object that
          have not yet had their guards verified.</li>

      <li>@('(BODY-USES-NON-COMPLIANT-FNS . fns)') -  @('fns') is a list of
          function symbols used in the body of the @('LAMBDA') object that
          have not yet had their guards verified.</li>

      <li>@('(UNPROVED-GUARD-CLAUSES . cl-set)') - @('cl-set') is the list of
          guard conjectures -- written as clauses -- that tau was unable to
          prove.</li>

      <li>@('RE-VALIDATION-INTERRUPTED') - an interrupt aborted the updating of
           this cache line</li>

      </ul>
     </li>
  <li>@(':hits') - The number of times @('apply$') has seen this @('LAMBDA')
      object</li>

  <li>@(':guard-code') - @('NIL') or the string ``&lt;code&gt;'' indicating that
      the guard has been compiled</li>

  <li>@(':lambda-code') - @('NIL') or the string ``&lt;code&gt;'' indicating that
      the @('LAMBDA') object has been compiled</li>

  </ul>

  <h3>Using This Information to Speed Up LAMBDA Application</h3>

  <p><i>Remember:</i> A lot of programmers spend enormous amounts of time and
  effort optimizing code that runs adequately fast!  Do not make the mistake of
  investing your time here unless you really have a critical ACL2 top-level
  read-eval-print form that you <i>know</i> runs too slowly!</p>

  <p>If you see a @('LAMBDA') object in the cache with @(':status') @(':BAD') then it
  is being interpreted.  If you believe it can be converted to @(':GOOD') and thus
  compiled, <i>and you believe you will @('apply$') it often enough in the future
  to warrant trying to speed it up,</i> then here are some tips.</p>

  <p>To be converted from @(':BAD') to @(':GOOD') a @('LAMBDA') has to be both
  well-formed and @(see guard) verified.  The cache doesn't try to verify
  objects that are not well-formed.  So first make sure your object is
  well-formed and then once it is make sure it is guard verified.</p>

  <p>If the @(':problem') is @('NOT-WELL-FORMED') the @(':lambda-object')
  does not pass the @(tsee well-formed-lambda-objectp) test.  That predicate
  gives no hint as to why, but if you call @(':')@(tsee translam) on the
  @(':lambda-object') it might give you more information.  E.g.,</p>

  @({
  ACL2 !>:translam (lambda (x) (bar x))

  ACL2 Error in TRANSLAM: The body of a LAMBDA object or lambda$ term
  should be fully badged but BAR is used in (BAR X) and has no badge.
  })

  <p>Other typical problems are that a function which was formerly in
  @(':logic') mode is now in @(':program') mode because of an undo, or the
  @('LAMBDA') object is not @(see tame), as in</p>

  @({
  ACL2 !>:translam (lambda (x) (apply$ (cons x 'nil) 'sq))

  ACL2 Error in TRANSLAM:  The body of a LAMBDA object or lambda$ term
  must be tame and (APPLY$ (CONS X 'NIL) 'SQ) is not.
  })

  <p>Here the @('LAMBDA') is unfixable because the arguments to @('apply$') are
  in the wrong order.  Typing the object correctly may fix the problem.</p>

  <p>In any case, you may need to extend the world to convert functions to
  @(':logic') mode, obtain @(see warrant)s (or at least @(see badge)s for
  functions that return multiple results), or even use a different @('LAMBDA')
  object.</p>

  <p>When you think you've got a well-formed @('LAMBDA') object, you can get
  the cache to update itself by applying the (new?) object in the (new?)
  world,</p>

  @({
  ACL2 !>(apply$ '(lambda (x) (apply$ 'sq (cons x 'nil))) '(5))
  25
  ACL2 !>(print-cl-cache)
  })

  <p>and see if the status is @(':GOOD') and, if not, what the @(':problem')
  is.</p>

  <p>If the problem is one of @('GUARD-USES-NON-COMPLIANT-FNS'),
  @('BODY-USES-NON-COMPLIANT-FNS'), or @('UNPROVED-GUARD-CLAUSES'), the
  @('LAMBDA') object is well-formed but not guard verified.  Again, you may
  need to further extend the world by calling @(tsee verify-guards) on the
  listed function symbols in first two problems or call @('verify-guard') on
  the lambda object itself for an opportunity to supply @(':hints') to prove
  the guard @(see clause)s listed in the third problem.</p>

  <p>For example, suppose we define @('squ') with a guard of @('natp'),</p>

  @({
  (defun$ squ (x)
     (declare (type (satisfies natp) x))
     (* x x))
  })

  <p>And suppose we define @('nfixer') to always return a natural number but
  in such a way as its type-prescription is weak.</p>

  @({
  (defun$ nfixer (x)
    (if (equal x (car (cons x x)))
        (nfix x)
        nil))
  })

  <p>Furthermore, let's disable @('nfixer') so the prover has no way of
  discovering the proper type.</p>

  @({
  (in-theory (disable nfixer))
  })

  <p>If we then</p>

  @({
  ACL2 !>(apply$ '(lambda (x) (squ (nfixer x))) '(5))
  25
  })

  <p>and use @('print-cl-cache'), we see that the @(':problem') is that @('NFIXER')
  is not guard verified.  So we</p>

  @({
  ACL2 !>(verify-guards nfixer)
  })

  <p>and try the @('apply$') and the @('print-cl-cache') again.  This time the @(':problem') is
  @('(UNPROVED-GUARD-CLAUSES ((NATP (NFIXER X))))').  So tau couldn't prove that
  @('NFIXER') returns a @('NATP').  We can thus</p>


  @({
  ACL2 !>(verify-guards (lambda (x) (squ (nfixer x)))
             :hints (("Goal" :in-theory (enable nfixer))))
  })

  <p>The @('verify-guards') should succeed.  Successful calls of
  @('verify-guards') on @('LAMBDA') objects updates the cache, so we don't have
  to ``trick'' the cache into updating itself by @('apply$')ing the @('lambda')
  again.  We can now just do @('(print-cl-cache)') and see the @(':status') is
  @(':GOOD').</p>

  <p>Whether all this work is worth is depends on how often you're going to execute
  this @('LAMBDA') object!</p>

  <h3>A Single Performance Comparison</h3>

  <p>Suppose we have defined @('squ') and @('nfixer'), disabled @('nfixer'),
  and verified the guards of @('nfixer') as above.  Additionally, define the
  @(see scion) that maps a predicate over a list and checks that the predicate
  holds for every element.</p>

  @({
  (defun$ always$ (pred lst)
         (if (endp lst)
             t
             (and (apply$ pred (list (car lst)))
                  (always$ pred (cdr lst)))))
  })

  <p>and define the function that builds a list of the first @('n+1') naturals
  and use it to define the misleadingly named constant @('*million*') which
  contains the first million and one naturals.</p>

  @({
  (defun nats-ac (n ac)
    (if (zp n)
        (cons 0 ac)
        (nats-ac (- n 1) (cons n ac))))

  (defconst *million* (nats-ac 1000000 nil))
  })

  <p>Now observe that @('(lambda (x) (natp (squ (nfixer x))))') suffers the
  same problem we witnessed above: tau cannot prove the guard clause because
  @('nfixer') is disabled.  So we can do an experiment!  How long does it take
  to run this @(':BAD') lambda object over the list @('*million*')?  And then,
  how long does it take to do it again after verifying its guards and turning
  its status to @(':GOOD')?</p>

  @({
  ACL2 !>(time$ (always$ '(lambda (x) (natp (squ (nfixer x)))) *million*))
  ; (EV-REC *RETURN-LAST-ARG3* ...) took
  ; 4.35 seconds realtime, 4.35 seconds runtime
  ; (128,000,160 bytes allocated).
  T

  ACL2 !>(verify-guards (lambda (x) (natp (squ (nfixer x))))
           :hints (("Goal" :in-theory (enable nfixer))))

  ...[successful but output elided]...

  ACL2 !>(time$ (always$ '(lambda (x) (natp (squ (nfixer x)))) *million*))
  ; (EV-REC *RETURN-LAST-ARG3* ...) took
  ; 0.19 seconds realtime, 0.19 seconds runtime
  ; (32,000,064 bytes allocated).
  T
  })

  <p>So we dramatically sped up the computation.  But we almost certainly spent
  longer than the original 4.35 seconds debugging the problems and converting
  the object's status to @(':GOOD').  So unless we're going to be doing this
  repeatedly in the future, it probably wasn't worth it!</p>")
other
(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>")
other
(defxdoc print-gv
  :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>

 <ul>

 <li>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').</li>

 <li>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.</li>

 <li>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).</li>

 </ul>

 <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><b>Remarks</b></p>

 <ul>

 <li>(1) @('Print-gv') starts by temporarily replacing the current installed
 ACL2 @(see world) with the world that was installed at the time the guard
 violation took place.  The current world is re-installed when @('print-gv')
 returns.  We illustrate this point with an example at the end of this
 topic.</li>

 <li>(2) The output from @('print-gv') always goes to the terminal.
 (Specifically, the output goes to the value of the constant @(tsee
 *standard-co*).)</li>

 <li>(3) While @('print-gv') is a utility for debugging @(see guard)
 violations, see @(see guard-debug) for a different sort of utility, which
 assists in debugging failed proofs arising from guard verification.</li>

 </ul>

 <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>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>We conclude with an example that illustrates point (1) above, regarding the
 installation of the @(see world) that was in place at the time the guard
 violation took place.  In the following, the @(tsee progn) call fails when the
 form @('(foo 3)') causes a guard violation.</p>

 @({
 (progn (defn g (x) (consp x))
        (defun foo (x) (declare (xargs :guard (g x))) (car x))
        (value-triple (foo 3)))
 })

 <p>We can then issue @('print-gv'):</p>

 @({
 ACL2 !>:print-gv

 (FLET ((FOO{GUARD} (X) (DECLARE (IGNORABLE X)) (G X))) (FOO{GUARD} 3))

 ACL2 !>
 })

 <p>However, if you try to evaluate this form, you will get an error because
 the function @('g') is not currently defined.  This problem can be solved by
 preceding @(':print-gv') with @(':redo-flat'), to re-run the events up to the
 one that failed; see @(see redo-flat).</p>")
other
(defxdoc print-object$
  :parents (io acl2-built-ins)
  :short "Print an object to an open object output channel"
  :long "
 @({
 General Form:
 (print-object$ x channel state)
 })

 <p>where @('x') is any ACL2 object and @('channel') is an open object output
 channel.  See @(see io).</p>

 <h3>Remarks</h3>

 <p>A newline is printed just above @('x').  To eliminate that newline or print
 a given comment instead, see @(see print-object$+).</p>

 <p>@('Print-object$') pays attention to the values of @(see print-control)
 variables.  To provide them as keyword arguments rather than assigning them
 globally, see @(see print-object$+).</p>

 <p>By default, the output of @('print-object$') is human-readable.  To use
 @(see serialize) printing instead, first set the serialize character using
 @(tsee set-serialize-character).</p>

 <p>For a related utility, see @(tsee write-list).</p>")
other
(defxdoc print-object$+
  :parents (io acl2-built-ins)
  :short "Print an object to an open output channel in a specified manner"
  :long "
 @({
 General Form:
 (print-object$+ x       ; an ACL2 object
                 channel ; an open object output channel
                 &key
                 header  ; nil or a comment string (see below)
                 serialize-character       ; as in with-serialize-character
                 print-base print-case ... ; print-control variables
                 )
 })

 <p>This macro is a more flexible variant of @(tsee print-object$).  Any of the
 print-control variables may be provided as a keyword; see @(see
 print-control).  All arguments are evaluated.</p>

 <p>The @(':header') is printed so that it immediately precedes @('x').  By
 default, a single newline is what is printed for the header.  If @(':header')
 is specified as @('nil') then no such header is printed.  Otherwise, the value
 @(':header') should be a string for which the first non-whitespace character
 (if any) on each line is a semicolon (@(';')).  If the last character of the
 string is not a newline, then a newline will be printed to separate the string
 from @('x').</p>

 <p>The @(':serialize-character') keyword argument has a default of @('nil').
 If it is supplied a value other than @('nil') or @(''nil') (even if it is
 supplied an expression other than those two constants), then it is an error to
 supply other keyword arguments.  Otherwise printing is done without
 serialization (see @(see serialize)).</p>")
other
(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>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>

 <p><b>Remarks on deviation from the @(tsee fmt) functions.</b></p>

 <ol>

 <li>The @(tsee evisc-table) is ignored by these functions that print to
 strings.  Use the @(':evisc-tuple') keyword instead.</li>

 <li>@(csee 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.</li>

 <li>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.</li>

 </ol>")
other
(defxdoc probe-file
  :parents (io programming-with-state)
  :short "Determine whether a file exists"
  :long "<p>ACL2 does not directly support the Common Lisp function,
 @('probe-file'), which indicates whether or not a given file exists.  But see
 @(see canonical-pathname) and see @(see file-write-date$) for ways to check in
 ACL2 whether a file exists.</p>")
other
(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 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>")
other
(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: ~x0"
                     (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: ~x0"
                  (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 evisc-tuple)

  ; 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 "~Y01"
           (untranslate (car terms) iff-flg wrld)
           evisc-tuple)
       (print-terms (cdr terms) iff-flg wrld evisc-tuple))))
 })")
other
(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 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>See @(see set-inhibit-output-lst) for how to control the printing done for
 each event.  By default, each event is printed before it is evaluated and a
 suitable value is printed after successful completion.  (Technical note:
 successful completion produces a multiple-value return that is an @(see
 error-triple) @('(mv nil val state)'); then the value @('val') is printed.)
 Printing of both the event and its value can both be inhibited by including
 the symbol, @('EVENT'), in your call of @('set-inhibit-output-lst').</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>

 <p>Remark on return value.  As with all @(see events), a call of @('progn')
 returns an @(see error-triple), @('(mv erp val state)'), where @('erp') is nil
 when the event is successfully admitted.  In that case, this is the
 error-triple returned by the final event in the @('progn') call, or @('(mv nil
 nil state)') if the form is just @('(progn)').</p>")
other
(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 and whether certifying or including it, 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
   (let ((live-st (cdr (assoc-eq 'st *user-stobj-alist*))))
     (update-fld 3 live-st)))
 })")
other
(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 !>
 })")
other
(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 @(see 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>")
other
(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>The constant @('*initial-program-fns-with-raw-code*') provides the initial
 value of @('(@ program-fns-with-raw-code)').  The value of that constant is
 the list of ACL2 source functions that have special raw-Lisp code.  It is
 important that these @(see program)-mode functions not be converted to @(see
 logic) mode.  Otherwise, one could arrange to prove a contradiction.  To see
 how, consider the following example, which takes advantage of an unsound use
 of @(':')@(tsee q) to prove that a call of a program-only function, @('p-o'),
 returns two different values on the same input (an obvious contradiction).</p>

 @({
 (defun p-o (x)
   (declare (xargs :guard t))
   (er hard? 'p-o
       "Attempted logical evaluation of ~x0."
       (list 'p-0 x)))

 :q ; exit the ACL2 read-eval-print loop

 (defun p-o (x)
   (declare (xargs :guard t))
   (atom x))

 (lp) ; re-enter the ACL2 read-eval-print loop

 (defthm p-0-nil-is-nil
   (equal (p-o nil) nil)
   :hints (("Goal" :in-theory (disable (:e p-o)))))

 (defthm p-o-nil-is-t
   (equal (p-o nil) t))
 })

 <p>In the ACL2 source one often finds a definition marked with readtime
 conditionals, such as the following.</p>

 @({
 (defun p-o (x)
   (declare (xargs :guard t))
   #-acl2-loop-only
   (atom x)
   #+acl2-loop-only
   (er hard? 'p-o
       "Attempted logical evaluation of ~x0."
       (list 'p-0 x)))
 })

 <p>The @('acl2-loop-only') annotations arrange that when ACL2 is built, one
 gets the effect described above, where the @('#+acl2-loop-only') code is used
 in the definition known to ACL2 and the @('#-acl2-loop-only') code is used in
 the definition known to raw Lisp.  All function symbols with such definitions
 are in the list mentioned above, that is, the value of the constant
 @('*initial-program-fns-with-raw-code*').</p>

 <p>In summary: The contradiction proved above explains the restriction that
 @(tsee logic)-mode functions may not call @(see program)-mode functions.</p>

 <p>See @(see safe-mode-cheat-sheet) for possible workarounds, which however
 may compromise soundness.</p>")
other
(defxdoc program-wrapper
  :parents (program programming advanced-features)
  :short "Avoiding expensive @(see guard) checks using @(see program)-mode functions"
  :long "<p>Application programs can benefit from avoiding expensive @(see
 guard) checks.  Imagine that @('expensive-guard-fn') is a function whose calls
 may be slow to evaluate, and that @('expensive-fn') is a function whose guard
 calls @('expensive-guard-fn').  So, when you call @('expensive-fn') at the top
 level, whether directly in the ACL2 read-eval-print loop or during @(tsee
 make-event) expansion, the guard check may be slow.  If you are confident that
 the guard check will pass, you may thus prefer to avoid it.</p>

 <p>The following contrived example shows how to avoid that guard check by
 using a <i>program-mode wrapper</i>: a function in @(see program) mode that
 calls the intended function directly.  The example below illustrates that idea
 by defining @('expensive-fn-wrapper') as a program-mode wrapper for
 @('expensive-fn').  That wrapper has a computationally inexpensive guard,
 typically @('t'), which avoids any expensive guard check: after the
 inexpensive guard check, the remaining computation takes place using raw Lisp
 computation, which doesn't do any guard checking.  (See @(see evaluation) for
 relevant background.)</p>

 @({
 (defun fib (n) ; Fibonacci function, just for an example of slow computation
   (declare (xargs :guard (natp n)))
   (if (zp n)
       0
     (if (eql n 1)
         1
       (+ (fib (- n 1))
          (fib (- n 2))))))

 (defun expensive-guard-fn (n)
   (declare (xargs :guard t))
   (and (natp n)
        (natp (fib n))))

 (defun expensive-fn (n)
   (declare (xargs :guard (expensive-guard-fn n)))
   (* 2 n))

 ; The following may take about a second, virtually all in the guard check.
 (time$ (expensive-fn 40))

 (defun expensive-fn-wrapper (n)
   (declare (xargs :mode :program))
   (expensive-fn n))

 ; The following is virtually instantaneous.
 (time$ (expensive-fn-wrapper 40))
 })

 <p>This trick isn't necessary if your function call is made on behalf of a
 superior call of a function that is guard-verified (or in program mode, since
 that essentially brings us back to the wrapper situation).  Consider the
 following definition, building on the example above.</p>

 @({
 (defun f (n)
   (declare (xargs :guard (natp n)))
   (expensive-fn n))

 ; The following is virtually instantaneous.
 (time$ (f 40))
 })

 <p>Then evaluation of @('(f 40)') is virtually instantaneous, for the same
 reason that evaluation of @('(expensive-fn-wrapper 40)') is virtually
 instantaneous: after the top-level guard check passes, the rest of the
 computation takes place without guard checks.  Note however that if we change
 the definition by removing guard verification, then the trick is once again
 helpful, as shown by continuing the examples above.</p>

 @({
 ; Define a logic-mode function that is not guard-verified:
 (defun g (n)
   (expensive-fn n))

 ; The following may take about a second, virtually all in the guard check.
 (time$ (g 40))
 })

 <p>Remark.  This trick may be less effective if you see an
 @('"Invariant-risk"') warning, which prevents computation from taking place
 within raw Lisp, thus avoiding guard checks; see @(see invariant-risk).</p>")
other
(defxdoc programming
  :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>If you are unfamiliar with Lisp, we suggest you start by reading @(see
 gentle-introduction-to-acl2-programming).</p>

 <p>If you are already familiar with Common Lisp (or even some other Lisp
 variant), then you may find it helpful to start with the topic, @(see
 introduction-to-programming-in-acl2-for-those-who-know-lisp).</p>

 <p>Also see @(see debugging) for utilities that can aid in programming.</p>")
other
(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 @(see gentle-introduction-to-acl2-programming).</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 typically converts to upper case when reading symbols
 (see @(see symbols) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> for details).  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
 either 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
 @(see gentle-introduction-to-acl2-programming)
 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>")
other
(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
 ensure 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>You may wish to modify state globals within a book, but this can be
 slightly problematic because only legal event forms (see @(see
 embedded-event-form)) may go into @(see books).  Fortunately there is a
 workaround using @('make-event'); see @(see make-event), in particular the
 section ``Examples Illustrating How to Access State''.</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.  (Note for advanced system hackers: There is also a stronger
 predicate, @('(state-p+ state)'), which for example implies the guards for
 @('fmt') and related functions.</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 discussion of guard generation from
 @(tsee xargs) fields of @(see declare) forms, specifically, for keywords
 @(':guard'), @(':stobjs'), and @(':dfs').</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.  A
 related utility that avoids the use of state is @('er-let*-cmp'); see @(see
 context-message-pair).</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 @(see 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>")
other
(defxdoc prohibition-of-loop$-and-lambda$
  :parents (defconst defmacro defpkg)
  :short "Certain events do not allow @(tsee loop$)s or @(tsee lambda$)s"
  :long "<p>Certain events, including @(tsee defconst), @(tsee defmacro), and
  @(tsee defpkg), prohibit the use of @(tsee loop$) and @(tsee lambda$).  The
  prohibition of @('loop$')s is due to their use of @('lambda$')s, so we
  focus on why @('lambda$')s are prohibited here.</p>

  <p>@('Lambda$') is prohibited in these events because of the way @(see books)
  are loaded.  To speed up the execution of @('include-book') the compiled file
  for a book is loaded before the events in the book are processed.  But the
  evaluation of @('lambda$') expressions in raw Lisp depends on the
  @('lambda$')s having been translated and recorded in the logical world and in
  the lambda cache (see @(tsee print-cl-cache)).  So the execution of these
  events can't depend on @('lambda$').</p>

  <p>If you have submitted an event that provoked an error citing this topic
  you must restate the event to avoid those prohibited constructions.
  <i>Unfortunately, you must also consider ancestral occurrences of the prohibited
  constructions!</i>  We first give two examples of the problem to drive home the
  message and then we discuss various ways the problem can be dealt with.</p>

  <h3>Examples of Prohibited Forms</h3>

  @({
  ACL2 !>(defconst *2^10* (apply$ (lambda$ (x) (expt 2 x)) '(10)))

  ACL2 Error in ( DEFCONST *2^10* ...):  We prohibit certain events,
  including DEFCONST, DEFPKG, and DEFMACRO, from being ancestrally dependent
  on loop$ and lambda$ expressions.  But at least one of these prohibited
  expressions occurs in this event.  See :DOC prohibition-of-loop$-and-
  lambda$.
  })

  <p>We will discuss how to avoid such errors in the next section.</p>

  <p>Here is an example of an ancestral use of @('lambda$') in a macro.
  Suppose we wish to define the macro @('rat') so that @('(rat "123.4567")')
  expands to the rational @('1234567/10000').  Our idea is to use @('loop$') in
  the definition of the function @('string-to-rat') and then to call
  @('string-to-rat') in our macro.  (We don't recommend this particular use of
  @('loop$')s to parse a string into a rational but we use it here to make a
  point later.)</p>

  @({
  (defun string-to-rat (str)
    (let* ((lst (coerce str 'list))
           (right-of-pt (length (cdr (loop$ for d in lst
                                            as tail on lst
                                            thereis
                                            (if (eql #. d) tail nil))))))
      (loop$ for tail on lst
             when (not (eql (car tail) #.))
             sum
             (* (- (char-code (car tail)) 48)
                (expt 10
                      (- (loop$ for d in tail sum (if (eql d #.) 0 1))
                         (+ 1 right-of-pt)))))))

  (defmacro rat (str) (string-to-rat str))
  })

  <p>The attempt to define the macro will provoke the error shown above for
  @('(defconst *2^10* ...)').</p>

  <h3>Avoiding These Errors</h3>

  <p>The only way to avoid these errors is to not use @('lambda$') or
  @('loop$') in these events!  We can fix the particular @('defconst') example
  above simply with</p>

  @({
  (defconst *2^10* (apply$ 'expt '(2 10)))
  })
  <p>or, better yet, by</p>
  @({
  (defconst *2^10* (expt 2 10))
  })

  <p>since there is reason @('apply$') is involved at all.</p>

  <p>When it is hard to avoid the prohibited constructs you might be able to
  use @('make-event') to do the necessary computation during the creation of
  the event, though this technique seems mainly applicable to @('defconst') and
  much less useful to the @('defmacro') case.</p>

  @({
  (make-event
    `(defconst *2^10*
      ',(apply$ (lambda$ (x) (expt 2 x)) '(10))))
  })

  <p>However, in general, removing all uses of @('loop$') and @('lambda$') can
  require a lot of re-coding.  For example, fixing the @('rat') macro requires
  several old-fashioned recursive definitions to carry out the iterations done
  with @('loop$').</p>

  @({
  (defun old-fashioned-string-to-rat1 (lst power)
    (cond
     ((endp lst) 0)
     ((eql (car lst) #.)
      (old-fashioned-string-to-rat1 (cdr lst) power))
     (t (+ (* (- (char-code (car lst)) 48)
              (expt 10 power))
           (old-fashioned-string-to-rat1 (cdr lst) (- power 1))))))

  (defun left-of-pt (lst)
    (cond ((endp lst) 0)
          ((eql (car lst) #.) 0)
          (t (+ 1 (left-of-pt (cdr lst))))))

  (defun old-fashioned-string-to-rat (str)
    (let ((lst (coerce str 'list)))
      (old-fashioned-string-to-rat1 lst (- (left-of-pt lst) 1))))

  (defmacro rat (str) (old-fashioned-string-to-rat str))
  })

  <p>Another way to eliminate @('loop$') and @('lambda$') is to replace the
  offending expressions with their translations.  There is no prohibition of
  fully-translated quoted @(tsee LAMBDA) objects, just of @('lambda$')
  expressions.</p>

  @({
  (defun string-to-rat (str)
    ((LAMBDA
      (LST)
      ((LAMBDA
        (RIGHT-OF-PT LST)
        (SUM$+
         '(LAMBDA
           (LOOP$-GVARS LOOP$-IVARS)
           (DECLARE (IGNORABLE LOOP$-GVARS LOOP$-IVARS))
           ((LAMBDA
             (RIGHT-OF-PT TAIL)
             (BINARY-*
              (BINARY-+ '-48 (CHAR-CODE (CAR TAIL)))
              (EXPT
               '10
               (BINARY-+
                (SUM$
                 '(LAMBDA (LOOP$-IVAR)
                          (DECLARE (IGNORABLE LOOP$-IVAR))
                          ((LAMBDA (D) (IF (EQL D '#.) '0 '1))
                           LOOP$-IVAR))
                 TAIL)
                (UNARY-- (BINARY-+ '1 RIGHT-OF-PT))))))
            (CAR LOOP$-GVARS)
            (CAR LOOP$-IVARS)))
         (CONS RIGHT-OF-PT 'NIL)
         (WHEN$+
          '(LAMBDA
            (LOOP$-GVARS LOOP$-IVARS)
            (DECLARE (IGNORABLE LOOP$-GVARS LOOP$-IVARS))
            ((LAMBDA (TAIL)
                     (NOT (EQL (CAR TAIL) '#.)))
             (CAR LOOP$-IVARS)))
          'NIL
          (LOOP$-AS (CONS (TAILS LST) 'NIL)))))
       (LENGTH
        (CDR
         (THEREIS$+
          '(LAMBDA
            (LOOP$-GVARS LOOP$-IVARS)
            (DECLARE (IGNORABLE LOOP$-GVARS LOOP$-IVARS))
            ((LAMBDA (D TAIL)
                     (IF (EQL '#. D) TAIL 'NIL))
             (CAR LOOP$-IVARS)
             (CAR (CDR LOOP$-IVARS))))
          'NIL
          (LOOP$-AS (CONS LST (CONS (TAILS LST) 'NIL))))))
       LST))
     (COERCE STR 'LIST)))
  })

  <p>If we define @('string-to-rat') as above then we can define the @('rat')
  macro as originally desired and the @('defmacro') is accepted.</p>

  <p>But there are several arguments against this approach in general:</p>
  <ul>

  <li>@('Defconst'), @('defmacro') and @('defpkg') not only prohibit
  @('loop$') and @('lambda$') but also prohibit all uses of @('apply$') and
  scions if user-defined functions are involved in the function objects.  This
  is because to compute logically with them one must have @(see warrant)
  hypotheses and there is no provision for supplying warrants with these
  events.  See @(see ignored-attachment).  It turns out that the hideous
  example above does not mention any user-defined functions in the function
  objects, so this restriction doesn't stop us here.</li>

  <li>Eliminating @('loop$') in favor of scions sacrifices execution speed
  if the @('loop$')s are guard verified.  A guard-verified @('loop$') executes
  in raw Lisp as a Common Lisp @('loop'), whereas its translation into nested
  calls of @('loop$') scions, even if guard verified, involves far more
  function calls.</li>

  <li>It is much harder to ``maintain'' code derived this way!</li>
  </ul>

  <p>There may be cases where no user-defined functions are involved,
  efficiency doesn't matter, and the @('loop$') scion translation of a
  @('loop$') is as perspicuous as the @('loop$') itself.  So don't dismiss this
  approach out of hand.</p>")
other
(defxdoc project-dir-alist
  :parents (books events)
  :short "Support for moving project directories (also @(':dir') arguments)"
  :long "<p>This topic describes the @('project-dir-alist'), which supports the
 relocation of book directories so that their @(see books) are still treated as
 certified.  Each such directory is treated as a <i>project</i>, which is
 represented by a @(see keyword).  In particular, the keyword, @(':SYSTEM'),
 represents the @(see community-books) as such a project.  The
 @('project-dir-alist') also provides one way to interpret the @(':dir')
 keyword argument of @(tsee include-book) and @(tsee ld).</p>

 <p>It is theoretically possible to undermine soundness by using this
 capability inappropriately (see below for some discussion of appropriate
 usage).  For the utmost security, perform a fresh certification of your entire
 collection of books without using this capability.  See @(see certificate),
 specifically the discussion there about placing a ``burden'' on the user.</p>

 <p>To see the @('project-dir-alist') in your session, evaluate the form
 @('(project-dir-alist (w state))').</p>

 <p>We start below by introducing the @('project-dir-alist') and explaining how
 to set it up.  Next we describe its effects.  We conclude by discussing some
 details, limitations, and restrictions.</p>

 <h3>What is the @('project-dir-alist') and how is it established?</h3>

 <p>The @('project-dir-alist') is an association list that maps keywords to
 directory names.  If we map keyword @(':K') to directory @('"<dir>"'), we
 say that the project name @('K') is associated with project directory
 @('"<dir>"').</p>

 <p>The way to establish the @('project-dir-alist') is to set environment
 variable @('ACL2_PROJECTS') to the name of a file, which we will call the
 ``projects file''.  The projects file may have lines of the following form,
 where we write @(':K') to denote an arbitrary keyword and @('"<dir>"') to
 denote a directory name inside double-quotes.</p>

 @({
 :K "<dir>"
 })

 <p>Such a line associates the project name @('K') with the project directory
 @('"dir"').  Each remaining line in a projects file should either be
 blank (i.e., contain only whitespace) or else be a comment line, that is, a
 line for which the first non-whitespace character is a semicolon (@(';')).</p>

 <p>The projects file is read when ACL2 starts up.  ACL2 creates the
 @('project-dir-alist') by using each line as above to associate the keyword
 @(':K') with the directory represented by @('"<dir>"'), which may be a
 relative or absolute pathname.  Relative pathnames are interpreted with
 respect to the directory of the projects file.</p>

 <p>If the keyword @(':SYSTEM') is not specified in the projects file, then the
 @('project-dir-alist') will additionally include a pair that associates
 @(':SYSTEM') with the @(see community-books) directory, which is generally the
 @('books/') subdirectory of your ACL2 distribution.  That value for
 @(':SYSTEM') can be overridden either by specifying it explicitly with
 @(':SYSTEM') in the projects file or by setting environment variable
 @('ACL2_SYSTEM_BOOKS') to that value &mdash; where if both overrides are used,
 they must not conflict.</p>

 <p>The values of the environment variables mentioned above, @('ACL2_PROJECTS')
 and @('ACL2_SYSTEM_BOOKS'), are pathnames that can be either relative or
 absolute.  A relative pathname is interpreted with respect to the directory in
 which ACL2 is invoked.  The final character need not be ``@('/')''; if it's
 not, then that character will be added at the end before adding to the
 @('project-dir-alist').</p>

 <p>The @('project-dir-alist') must have no duplicate keys and no duplicate
 directory names.</p>

 <h3>Effects of the @('project-dir-alist')</h3>

 <p>There are the following two effects of the association of a keyword @(':K')
 with a directory @('"<dir>"') in the @('project-dir-alist').</p>

 <p><b>(1) @(':K') specifies a project directory that may be moved.</b></p>

 <blockquote>

 <p>Consider first the default case, where there is a single association in the
 @('project-dir-alist'): @(':SYSTEM') is associated with the @(see
 community-books) directory.  Suppose that the community books and their
 certificates are moved to a new directory, @('"<dir>"').  Then if you run
 ACL2 in an environment where the @('project-dir-alist') associates
 @(':SYSTEM') with @('"<dir>"'), the relocated community books will still be
 treated as certified.</p>

 <p>The case of @(':SYSTEM') described above generalizes naturally, as follows.
 Let @('S') be a set of books certified with a given @('project-dir-alist'),
 each of which includes only other books in @('S').  (For example, @('S')
 contains just the community books directory in the special case above.)  Also
 assume that the absolute pathname of every book in @('S') has a prefix among
 the directories in that @('project-dir-alist').  Then all books in @('S'),
 along with their @(see certificate) files, can be moved and those books will
 still be considered to be certified in any ACL2 session with a suitable
 @('project-dir-alist'), as follows.  For every keyword @(':K') mapped to
 directory @('"<dir>"') in the original @('project-dir-alist') (the one at
 certification time), the new @('project-dir-alist') should map @(':K') to the
 directory @('"<dir2>"') to which @('"<dir>"') was moved.</p>

 </blockquote>

 <p><b>(2) @(':K') can be used as a @(':dir') keyword, to reference
 @('"<dir>"').</b></p>

 <blockquote>

 <p>The optional @(':dir') keyword argument of @(tsee include-book) and @(tsee
 ld) can have value @(':K'), in which case the pathname argument is interpreted
 with respect to @('"<dir>"').  This behavior is the same as when @(':K') is
 bound to @('"<dir>"') using @(tsee add-include-book-dir) or @(tsee
 add-include-book-dir!).</p>

 </blockquote>

 <h3>Additional details</h3>

 <blockquote>

 <p><b>Prefixes.</b> Suppose @(':K1') and @(':K2') are keywords bound in the
 @('project-dir-alist') to @('"<dir1>"') and @('"<dir2>"'), respectively,
 where @('"<dir1>"') is a prefix of @('"<dir2>"') (hence is strictly
 shorter, since duplicates are disallowed, as noted above).  Then it may be
 simplest to maintain that property &mdash; that the value of @(':K1') is a
 prefix of the value of @(':K2') &mdash; when creating a new @('ACL2_PROJECTS')
 directory to reflect relocation of these directories of books.  The actual
 requirement is that directories under the old value of @(':K2') need to be
 moved to the same relative locations under the new value of @(':K2'), and all
 other directories under the old value of @(':K1') need to be moved to the same
 relative locations under the new value of @(':K1').</p>

 <p><b>@(tsee Save-exec).</b> By default, an executable created with @(tsee
 save-exec) will have an unchanged @('project-dir-alist').  However, a new
 @('project-dir-alist') will be created as described above if environment
 variable @('ACL2_PROJECTS') is set; also, if environment variable
 @('ACL2_SYSTEM_BOOKS') is set, then the existing @('project-dir-alist') will
 be modified to map @(':SYSTEM') to the value of @('ACL2_SYSTEM_BOOKS').</p>

 </blockquote>

 <h3>Additional Limitations and Restrictions</h3>

 <blockquote>

 <p>(Already noted above) <b>No duplicates.</b> There must be no duplicate keys
 or duplicate directory names in the @('project-dir-alist').</p>

 <p><b>No overlap.</b> No keyword may be bound with @(tsee
 add-include-book-dir) or @(tsee add-include-book-dir!) that is also bound in
 the @('project-dir-alist').</p>

 <p><b>Avoid using absolute pathnames in books.</b> Consider a form that
 contains an absolute pathname, such as @('(defconst *c*
 "/u/home/jones/bk")').  If that form is in a book @('B') that is moved, then
 of course it remain in @('B') after the move.  That is certainly fine, unless
 one expects this pathname to change as @('B') is moved.  That said, an
 absolute pathname that extends a project directory is OK in an @(tsee
 include-book) form among the @(see portcullis) commands for a book, in the
 following sense: it is replaced in that book's @(see certificate) by
 referencing the project's keyword name to avoid using an absolute
 pathname.</p>

 </blockquote>")
other
(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 in raw Lisp, including @(see breaks) from the ACL2 loop, can be
 adjusted by ACL2 to include the string @('"[RAW LISP')"], at least for most
 Common Lisp implementations.  That change can help to remind users not to
 submit ACL2 forms there.  That adjustment is made by executing the following
 form in raw Lisp (for example, after typing @(':')@(tsee q)).</p>

 @({
 (install-new-raw-prompt)
 })

 <p>To return to printing the original Lisp prompt in raw lisp, evaluate the
 following in raw Lisp.</p>

 @({
 (install-old-raw-prompt)
 })")
other
(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).  Note that the package name (see @(see
 symbol-package-name) is irrelevant for these commands (though not their
 arguments); for example @('(dive 3)'), @('(acl2::dive 3)'), @('(acl2-pc::dive
 3)'), and @('(:dive 3)') are all equivalent.  For a list of perhaps the most
 commonly used commands, see @(see proof-builder-commands-short-list).</p>

 <p>The proof-builder supports user-defined macros, which are tactics that
 generate proof-builder instructions.  See @(see define-pc-macro).</p>

 <p><i>Remark.</i>  The ``pc-'' prefix, for example in ``define-pc-macro''
 above, stems from an earlier name for the proof-builder, which was
 ``proof-checker''.  That also accounts for the string @('"PC"') in the
 package name, @('"ACL2-PC"').</p>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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-acl2.el') distributed with
 ACL2 (in either of two directories; see @(see emacs)).</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>")
other
(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>")
other
(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>")
other
(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*).</p>")
other
(defxdoc proper-consp
  :parents (lists acl2-built-ins)
  :short "Recognizer for proper (@('nil')-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)")
other
(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>")
other
(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>")
other
(defxdoc provisional-certification
  :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>

 @({
  cert.pl --pcert-all -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>")
other
(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)")
other
(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>")
other
(defxdoc pso
  :parents (output-controls)
  :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.  Also see @(see gag-mode).</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>The ``Time'' printed in the summary shows the original times for the proof
 attempt, not the times for processing the @(':pso') command.</p>

 <p>Also see @(see pso!), @(see psog), @(see psof), @(see set-gag-mode), @(see
 set-inhibit-output-lst), and @(see set-print-clause-ids).</p>")
other
(defxdoc pso!
  :parents (output-controls)
  :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>")
other
(defxdoc psof
  :parents (output-controls)
  :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>")
other
(defxdoc psog
  :parents (output-controls)
  :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>")
other
(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+'): evaluating a function on explicit arguments while assuming
 that @(see warrant) hypotheses are true</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 @(see clause)s (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>")
other
(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>Other than the few exceptions noted later below, a ``puffable'' @(see
 command) is an @(tsee encapsulate), @(tsee include-book), or @(tsee
 certify-book) @(see 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 a few exceptions.</p>

 <ul>

 <li>An @(tsee encapsulate) command that generates @(see unknown-constraints),
 such as one generated by the macro @(tsee define-trusted-clause-processor), is
 not puffable.</li>

 <li>When an @(tsee encapsulate) has a non-empty @(see signature), it is not
 puffable if the `puff' command issued is @(':')@(tsee puff*), rather than
 @(':')@('puff').  That is because puffing may fail in this case, as discussed
 immediately below, and it may be annoying to deal with the failure, for
 example if @(':puff*') takes a long time to run.</li>

 <li>An attempt to puff may fail for an @(tsee encapsulate) with a non-empty
 @(see signature) that contains at least one use of @(tsee make-event) and also
 comes from a certified book.  The reason is that local definitions may be
 elided.  Here is an example of such a book.

 @({
 (in-package "ACL2")

 (encapsulate
   ((f (x) t))
   (make-event '(local (defun f (x) (cons x x))))
   (defthm f-prop (consp (f x))))
 })

 If we first certify this book, then we include it in a new ACL2 session, and
 next we issue the command @(':puff 1'), then we can see that the local
 definition in our @('encapsulate') event has been elided:

 @({
 ACL2 !>:pcb! 1
            1  (ENCAPSULATE
                    ((F (X) T))
                    (RECORD-EXPANSION
                         (MAKE-EVENT '(LOCAL (DEFUN F (X) (CONS X X))))
                         (LOCAL (VALUE-TRIPLE :ELIDED)))
                    (DEFTHM F-PROP (CONSP (F X))))
                (DEFTHM F-PROP (CONSP (F X)))
 ACL2 !>
 })

 Now an attempt to execute the command, @(':puff 1'), causes an error because
 @('f') lacks a definition.

 @({
 ACL2 !>:puff 1


 ACL2 Error in ( DEFTHM F-PROP ...):  The symbol F (in package "ACL2")
 has neither a function nor macro definition in ACL2.  Please define
 it.  See :DOC near-misses.  Note:  this error occurred in the context
 (F X).

 ACL2 !>
 })</li>

 <li>Similarly, a @(tsee local) event that involves @(tsee make-event)
 expansion may be elided when the event is from a book whose @(tsee
 include-book) form has been puffed.  This will result in an error if the
 elided event is necessary to support later events in the @('puff') of the
 command.  Here is an example, where the attempt to puff an @('include-book')
 for this book will fail, giving an error for @('( DEFUN G ...)') stating that
 the symbol @('F') has not been defined.

 @({
 (in-package "ACL2")
 (make-event '(local (defun f (x) x)))
 (local (defun g (x) (f x)))
 })</li>

 <li>An attempt to @('puff') an @(tsee include-book) command may fail for a
 book that has been modified, as described later in this documentation
 topic.</li>

 <li>The @('puff') of 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.  Also, ACL2 considers that (certified) book to have been included;
 future attempts to include that book will be considered to be @(see
 redundant).</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>")
other
(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)).  See @(see puff) for the definition of ``puffable'' and
 for a description of the basic act of ``puffing'' a @(see command).
 @('Puff*') is just the recursive application of @(see puff): it puffs not only
 the indicated command, but all of the commands thus generated, and recursively
 until none of the resulting commands can be puffed.  As noted in the
 documentation for @(see puff), @(':puff') should be viewed as a sort of hack;
 hence so should @('puff*').  @('Puff*') prints the region @(see puff)ed, using
 @(tsee pcs).</p>

 <p>Thus, 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.  NOTE: because one call of @(':puff*') may give rise
 to many calls of @(':puff'), it can take considerable time for a call of
 @(':puff*') to complete when many books are involved.</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>@(':Puff*') may cause an error, for example because of a name conflict
 caused by two different local lemmas with the same name, or because a @(tsee
 local) event in a book has been elided (see @(see puff)).  By default, the
 logical @(see world) is reverted to its value before that execution of
 @('puff*').  However, if the optional Boolean second argument is @('t'), then
 the world is preserved from the successful @(':puff') commands executed before
 the failed one.  That behavior can help with debugging, since both the warning
 message and the return value tell you which command could not be puffed
 successfully.</p>")
other
(defxdoc push-untouchable
  :parents (defttag)
  :short "Add name or list of names to the list of untouchable symbols"
  :long "<p>Untouchables are functions that cannot be called, as well as @(see
 state) global variables (see @(see programming-with-state)) that cannot be
 modified or unbound.  Macros can also be untouchable in some sense; see @(see
 defmacro-untouchable).</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>As noted above, macros may not be made directly untouchable; the macro
 @(tsee defmacro-untouchable) is provided for that purpose.  Thus, it is an
 error to evaluate @('(push-untouchable F t)') if @('F') is already a macro
 name, and it is also an error to define @('F') as a macro when @('F') has been
 made an untouchable function using @('(push-untouchable F t)').</p>

 <p>When a symbol is on the untouchables list it is syntactically illegal for
 any event to call a function 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 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>")
other
(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)")
other
(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)")
other
(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 @(see Tours).</p>

 <p>Generally, the topics listed above will not be of use to the ACL2
 user.</p>")
other
(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>")
other
(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>")
other
(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 produced 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>")
other
(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>You may also issue the command @('(value :q)') to exit the ACL2 loop.  More
 generally, if the result of evaluating a form in the ACL2 loop is the @(see
 error-triple) @('(nil :q state)'), the ACL2 loop will be exited.</p>

 <p>WARNING: The issuance of commands to raw Lisp may render your ACL2 session
 unsound.  Furthermore, evaluation of forms after exiting the ACL2 loop with
 @(':q') (or @('(value :q)'), etc.) is not guaranteed to agree with their
 evaluation in the ACL2 loop.  Specifically, Common Lisp may read an expression
 with the backquote character (@('`')) differently from how ACL2 reads the
 expression.  (The technical reason, in Common Lisp parlance, is that ACL2
 installs its own readtable in the ACL2 loop, which includes a custom backquote
 reader.)  Results of evaluation may have surprising differences depending on
 whether evaluation takes place in the ACL2 loop or in raw Lisp, as illustrated
 by the following log produced using an ACL2 executable built on SBCL.</p>

 @({
 ACL2 !>(car (quote `(a b c)))
 QUOTE
 ACL2 !>:q

 Exiting the ACL2 read-eval-print loop.  To re-enter, execute (LP).
 * (car (quote `(a b c)))
 SB-INT:QUASIQUOTE
 *
 })

 <p>To minimize discrepancies (including that one) between ACL2 and raw Lisp,
 use @(see raw-mode) instead of exiting the ACL2 loop.</p>

 <p>Unlike all other keyword commands, typing @(':q') is not equivalent to
 invoking the function @('q').  There is no function @('q').</p>")
other
(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? See @(tsee
 solution-to-ACL2-quantifier-exercise-2) for a solution.</p>")
other
(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>")
other
(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>")
other
(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))))
 })")
other
(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))))
 })")
other
(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-system 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>For an example of where this capability has proven useful, see
 @(see without-subsumption).  That tool uses @(tsee set-case-split-limitations)
 as well, since that is another way to control the prover's handling of
 propositional logic.</p>

 <p>To turn the heuristic back on:</p>

 @({
  (defattach-system quick-and-dirty-srs quick-and-dirty-srs-builtin)
 })")
other
(defxdoc quit
  :parents (good-bye)
  :short "Quit entirely out of Lisp"
  :long "<p>Same as @(tsee good-bye).</p>")
other
(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>")
other
(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)")
other
(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)")
other
(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$)")
other
(defxdoc random-remarks-on-rewriting
  :parents (rewrite rewrite-quoted-constant)
  :short "Some basic facts about the ACL2 rewriter"
  :long "<p>The ACL2 rewriter is technically part of the simplifier, but in
  this documentation we often conflate the two and say things like ``the
  conclusion simplifies to @('T')'' when in fact we should say ``the conclusion
  rewrites to @('T') during simplification'' In addition, both the simplifier
  and the rewriter are enormously complicated and contain so many heuristics
  that users are not often helped by studying the details.  For example, the
  rewriter takes 18 arguments (some of which are bundles of more rarely used
  arguments) and is part of a mutually recursive clique containing 50 functions
  as of Version 8.3, including the linear (and non-linear) arithmetic
  semi-decision procedures.  The rewriter and its clique consume about 6500
  lines of code.</p>

  <p>But to understand how @(':')@(tsee rewrite), @(':')@(tsee
  rewrite-quoted-constant), @(':')@(tsee linear), @(':')@(tsee congruence),
  @(':')@('forward-chaining') and other rules behave, the user has to have a
  fairly weak model of the simplifier and rewriter, so we sketch that here.</p>

  <p>In ACL2, the goals you see printed in proof output are represented
  internally as clauses.  See @(see clause).</p>

  <p>The job of the simplifier is to simplify a clause, returning a set of
  clauses whose conjunction is propositionally equivalent to the input clause.
  The most desirable output set is the empty set, because the conjunction over
  the empty set is @('T'), which means the goal clause was proved.  For related
  discussions, see @(see hints-and-the-waterfall), where we discuss how
  repeated simplifications are performed.</p>

  <p>Note that if you are trying to simplify the clause @('(lit1 lit2
  ... litk)') and you manage to rewrite, say, the @('liti') to @('T'), then the
  clause is true.  Furthermore, when rewriting a literal of a clause you may
  assume all the other literals false because if one were true the clause would
  be true.  Finally, when you rewrite a literal you are justified in replacing
  it with one that is propositional equivalent, since the literals are
  disjoined.</p>

  <p>The simplifier works by first generating several data structures, here
  called the ``context,'' which codify governing assumptions available for the
  rewriting of each literal.  These data structures include the @(see
  type-alist) and @(see linear-arithmetic) data base.  They are built using
  various rules derived from previously proved lemmas, including @(':')@(tsee
  type-prescription), @(':')@(tsee forward-chaining), and @(':')@(tsee linear)
  rules.  It then calls the rewriter successively on each literal passing it
  the appropriate context and stipulating that the result of the rewriting must
  be propositionally equivalent to the input.  The rewriter returns a suitable
  term.  If the result is the unchanged, the simplifier just moves on to the
  next literal.  If the result contains no @('IF')-expressions, the simplifier
  just replaces the old literal with the new one.  But if the new term contains
  @('IF')-expressions, the simplifier splits them out into a set of clause
  segments, i.e., if the literal simplifies to @('(IF a b c)'), then the
  simplifier gets two new clause segments, @('((NOT a) b)') and @('(a c)'), and
  then it splices each segment into the goal clause where the literal was,
  producing a set of new clauses, and then resumes rewriting literals in each
  new clause.  Heuristics try to prevent excessive case splitting, e.g., see
  @(see case-split-limitations).</p>

  <p>The job of the rewriter is to take a term, some context, and an
  equivalence relation, and return a ``simpler'' term that is equivalent to the
  input term under the assumptions in the context.</p>

  <p>The rewriter works by exploring the term, possibly changing the context
  and the equivalence relation as appropriate for the subterms it rewrites.</p>

  <ul>

  <li>If the term is a variable, the rewriter just returns it (unless the
  context tells it something interesting about that variable, such as that the
  variable is equal to @('nil')).  Sometimes you might wish that the value of a
  bound variable be rewritten, usually because the value found on the alist was
  rewritten under a different equivalence relation than the variable is now
  being used.  See @('double-rewrite').</li>

  <li>If the term is a quoted constant, the rewriter tries to apply
  @(':')@(tsee rewrite-quoted-constant) rules to that constant.</li>

  <li>If the term is @('(IF a b c)'), it rewrites the test, @('a'), under the
  equivalence relation @('IFF') to get some (possibly) new term, @('a'').  If
  @('a'') is @('nil') or is obviously different from @('nil') (like @('T')),
  the rewriter replaces the @('IF')-term by @('b') or @('c'), appropriately,
  and rewrites that.  If on the other hand, the rewriter can't decide whether
  @('a'') is @('nil') or not, it rewrites @('b') to @('b'') in an extended
  context in which @('a'') is assumed non-@('nil') and rewrites @('c') to
  @('c'') in an extended context in which @('a'') is @('nil').  In rewriting
  both branches it preserves the outer equivalence relation -- the one to be
  maintained while rewriting the @('IF')-term.  Then the rewriter returns
  @('(IF a' b' c')').</li>

  <li>If the term is a call of an arithmetic inequality, like @('(< a b)'), the
  rewriter rewrites @('a') and @('b') and then considers whether the context
  allows it deduce the truth or falsity of the inequality using a @(see
  linear-arithmetic) decision procedure.  The decision procedure, which is
  complete for linear inequalities over the rationals, uses heuristics to
  decide many integer cases, to select the order in which inequalities are
  combined to eliminate variables, and to handle some @(see
  non-linear-arithmetic) problems.</li>

  <li>If the term is a call of a function symbol, @('fn'), on some argument
  terms, @('a1'), ..., @('an'), the rewriter rewrites each argument, @('ai') to
  @('ai'').  For each argument the rewriter uses known @(':')@(tsee congruence)
  rules to determine which equivalence relations can be used to rewrite terms
  in that argument position so as to maintain the outer equivalence.  Then,
  having transformed @('(fn a1 ... an)') to @('(fn a1' ... an')') the rewriter
  tries to apply @(':')@(tsee rewrite) rules to that transformed term, called
  the ``target.''.</li>

  <li>Among the rewrite rules generally available for @('(fn a1' ... an')') is
  the definition of @('fn') itself.  The rewriter considers ``expanding'' the
  call, i.e., replacing it by the body of @('fn') after substituting the
  @('ai'') for the formal variables, if the definition is @(see enable)d, and
  then rewriting that.  But heuristics are used to prevent the indefinite
  expansion of recursive definitions.</li>

  </ul>

  <p>For an elementary tutorial on the application of a @(':')@('rewrite') rule
  to a target term, see @(see introduction-to-rewrite-rules-part-1) and @(see
  introduction-to-rewrite-rules-part-2).  Those topics also lead to
  documentation on how to design effective rules.  But just to summarize very
  briefly, we offer the following.</p>

  <p>@(':Rewrite') rules take the general form</p>

  @({
  (implies (and hyp1 ... hypk) (equiv lhs rhs))
  })

  <p>where @('equiv') is a known @(see equivalence) relation.  Recall that the
  rewriter has a target term to rewrite in some context and is required to
  return a term that is equivalent modulo a given equivalence relation, here
  called the ``outer'' equivalence.  Furthermore, if the target term is a
  function application, e.g., @('(fn a1' ... an')'), the argument subterms have
  already been rewritten.</p>

  <p>If the rule in question is enabled and its @('equiv') refines the outer
  equivalence, the rewriter tries to match @('lhs') with the target.  By
  ``match'' we mean it tries to find a substitution for the variables in
  @('lhs') that make the instantiated @('lhs') identical to the target.  We
  discuss matching further below.  Second, having found a suitable
  substitution, tries to ``relieve'' the hypotheses, as discussed below.  If
  successful, that means each @('hypi'), when instantiated with the
  substitution, is non-@('nil').  Third, if all the hypotheses are relieved,
  the target is ``replaced'' by the result of rewriting @('rhs') under the
  substitution.  We discuss that step more below too.</p>

  <p><b>Matching</b>: Technically, ACL2 uses a restriction of ordinary
  first-order unification -- the restriction being that only variables in the
  pattern (here the @('lhs') of the rule) may be instantiated.  Thus, the
  pattern @('(G x (H x))') matches @('(G (M A B) (H (M A B)))') by binding
  @('x') to @('(M A B)').  It does not match @('(G (M A B) (H (M A A)))') even
  though those two terms ``unify'' by binding @('x') to @('(M A A)') and @('B')
  to @('A').  Our pattern matcher is the function @('one-way-unify') in our
  source code.</p>

  <p>However, our pattern matcher knows some things about the structure of
  quoted constants.  For example, the pattern @('(CONS x y)') matches the
  quoted constant @(''(A B C)'), by binding @('x') to @(''A') and @('y') to
  @(''(B C)').  This can be seen by running @('one-way-unify') on those two
  terms:</p>

  @({
  ACL2 !>(one-way-unify '(cons x y) ''(A B C))
  (T ((Y QUOTE (B C)) (X QUOTE A)))
  })

  <p>Note the quote marks in our input.  Since @('one-way-unify') expects both
  of its arguments to be fully translated formal terms, we have to quote every
  constant we write here.  And since the arguments to @('one-way-unify') are
  evaluated before the function is called, we have to quote the two terms.  We
  see that @('one-way-unify') returns two results.  The first is @('T'),
  meaning that a suitable substitution was found.  The second is the
  substitution.  Lisp's abbreviation convention for printed ``dotted pairs,''
  its ``quote convention,'' its convention of reading symbols in uppercase, and
  our convention here of writing terms (and variables) in lower case but
  constants in upper case, all conspire to make the substitution a little hard
  to read for novices.  Another way to display the exact same substitution
  is:</p>

  @({
  ((y . '(B C)) (x . 'A))
  })

  <p>i.e., @('x') is bound to @(''A') and @('y') is bound to @('(B C)').</p>

  <p>Below are some other examples, but we've re-displayed the substitutions.</p>


  @({
  ACL2 !>(one-way-unify '(coerce x 'string) ''"Hello!")
  (T ((x . (#H #e #l #l #o #!))))
  ACL2 !>(one-way-unify '(intern-in-package-of-symbol x y) ''ACL2::TEMP)
  (T ((y . 'TEMP) (x . '"TEMP")))
  ACL2 !>(one-way-unify '(binary-+ '3 x) ''7)
  (T ((X . '4)))
  ACL2 !>(one-way-unify '(unary-- x) ''-7)
  (T ((X QUOTE 7)))
  ACL2 !>(one-way-unify '(unary-- x) ''7)
  (NIL NIL)
  ACL2 !>(one-way-unify '(binary-* '2 y) ''8)
  (T ((Y QUOTE 4)))
  ACL2 !>(one-way-unify '(binary-* x y) ''8)
  (NIL NIL)
  })

  <p>Note that the pattern matching algorithm is incomplete on quoted
  constants!  For example, it fails to match @('(unary-- x)') with @(''7') even
  though @('(unary-- '-7)') is @(''7').  It similarly fails to match
  @('(binary-* x y)') with @(''8') even though @('(binary-* '33 '8/33)') is
  @('8'); indeed, there are in infinite number of suitable substitutions for
  this case, but @('one-way-unify') is designed to return at most one so as to
  limit the applicability of rewrite rules to ``reasonable'' cases.</p>

  <p><b>Relieving the Hypotheses</b>: The hypotheses of a rewrite rule are
  relieved one at a time starting with the left-most one.  The basic strategy
  is just to rewrite each hypothesis, assuming the current context and if
  @('IFF') equivalence relation.  If the result comes back non-@('NIL') the
  hypothesis is equivalent to @('T') in the current context.  But there are
  various special considerations.</p>

  <ul>

  <li>Free variables: It is possible that a hypothesis contains variables that
  are not bound by the substitution generated by the match.  We call these
  ``free variables'' and the system tries to bind them to make the instantiated
  hypothesis appear among the contextual assumptions.  New bindings are
  accumulated as hypotheses are relieved.  It is possible to find multiple
  successful substitutions, some possibly filtered out by subsequent
  hypotheses.  See @('free-variables') and the documentation topics it
  cites.</li>

  <li>Pragmas: It is possible to mark a hypothesis so that it is temporarily
  assumed true so that the rewrite rule can be applied.  This essentially
  spawns another subgoal to prove the hypothesis and thus brings the full power
  of the prover (not just the rewriter) to bear on the hypothesis.  See @(tsee
  force) and @(tsee case-split).  It is also possible to include hypotheses
  that are logically always true but which cause the attempt to apply the rule
  to fail if a certain user-specified computation so indicates.  This can be
  used to restrict the application of a rule to certain syntactic situations.
  See @('syntaxp').</li>

  </ul>

  <p><b>Replacement</b>: Before the target is replaced by the rewritten
  @('rhs'), a heuristic check is made to prevent certain trivial forms of
  rewrite loops.  See @(tsee loop-stopper).  Otherwise, if the hypotheses are
  relieved (or assumed), the rewriter rewrites @('rhs') under the substitution
  generated by the match and the hypotheses.  It then makes certain heuristic
  checks to decide if replacing the target by this new term is a ``good idea''
  in the opinion of the ACL2 implementors.  The two main checks are designed to
  avoid runaway expansion of recursive functions (see @(see definition)), and
  introducing ``too many @(tsee IF)s'' (see @(see too-many-ifs).  The latter
  check is used to prevent unmanageable case explosions.  (In general, the
  number of cases rises exponentially with the number of @('IF')s.)</p>")
other
(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>")
other
(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)")
other
(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>")
other
(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 it may help to see :DOC raw-lisp-error.

 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>Resource errors, e.g., when attempting to evaluate @('(expt 2 (expt 2
 1000000))').  (We have seen raw Lisp errors when evaluating that expression in
 ACL2 built on host Lisps CCL, SBCL, and Allegro CL.)</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>

 <li>Certain errors during proofs (for an example see @(see
 live-stobj-in-proof)</li>

 </ul>")
other
(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)")
other
(defxdoc read-file-into-string
  :parents (io)
  :short "The contents of a file (or part of it) as a string"
  :long "<p>This macro returns the contents of the file, or a specified part of
 the file, as a string.  Otherwise, it returns @('nil') or causes an error.
 Although this macro implicitly takes the ACL2 @(see state), it differs from
 other ACL2 file-reading utilities in that it does not return the ACL2
 @('state'), and it is generally <i>much</i> faster.</p>

 <h3>Summary</h3>

 @({
 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)
 (read-file-into-string "foo.lisp" :start 20000 :bytes 10000 :close t)

 General Form:

 (read-file-into-string filename ; a filename relative to the current directory
                        :start s ; default 0
                        :bytes b ; default nil
                        :close c ; default :default
                        )
 })

 <p>where @('filename') is a string, which is typically the name of a file, and
 the keyword arguments, which are optional and evaluated, are as follows:
 @('s') has default @('0') and its value is a natural number, where an error
 occurs if that number exceeds the length of the given file; @('b') has default
 @('nil') and its value is either a natural number or @('nil'); and @('c') has
 default @(':default') and its value is otherwise considered to be false (when
 @('nil')) or true (when not @('nil')).  The effects of these arguments are
 described below.</p>

 <p>For examples, see @(see community-books) file
 @('books/system/tests/read-file-into-string.lisp').</p>

 <h3>Summary documentation</h3>

 <p>Typical use of @('read-file-into-string') will either return the contents
 of the given file (as a string) or will return specified segments of the file.
 Here is a log illustrating how we can read the full contents of a file and
 then read it in pieces.  The form @('(INCREMENT-FILE-CLOCK STATE)') is
 necessary in order to make certain successive calls; this is discussed further
 below.</p>

 @({
 ACL2 !>(read-file-into-string "tmp.txt")
 "Hello
 world.
 "
 ACL2 !>(INCREMENT-FILE-CLOCK STATE)
 <state>
 ACL2 !>(read-file-into-string "tmp.txt" :start 0 :bytes 3)
 "Hel"
 ACL2 !>(read-file-into-string "tmp.txt" :start 3 :bytes 2)
 "lo"
 ACL2 !>(read-file-into-string "tmp.txt" :start 5)
 "
 world.
 "
 ACL2 !>
 })

 <p>For two successive calls of @('read-file-into-string') on the same input
 string, the second call must generally start beyond the last byte that was
 read by the first call.  An exception is made when the second call specifies
 @(':bytes 0'), when @(':start') is either omitted or has value 0; in that
 case, the empty string is returned without error.  An exception is also made
 when the form @('(INCREMENT-FILE-CLOCK STATE)') is evaluated between the two
 calls.</p>

 <p>It may seem odd to require a call of @('increment-file-clock') to avoid
 errors from successive reads.  The reason stems from the fact that
 @('increment-file-clock') is a function.  The concern is that the file may
 change between successive calls of @('read-file-into-string') (perhaps made
 hours apart!), for reasons external to ACL2, in which case it could appear
 that @('read-file-into-string') returns different values for the same inputs.
 By evaluating @('(INCREMENT-FILE-CLOCK STATE)'), one is incrementing the
 file-clock field of the @('state') argument, so the next call is on a
 different @('state') argument.  This is all explained logically by the
 definitions of @('read-file-into-string') and its subroutines in ACL2, as
 shown in the final section of this documentation.  (But the implementation of
 @('read-file-into-string') involves raw Lisp code.)  ACL2 causes various
 informative Lisp errors when functional semantics could otherwise be violated,
 and some of these errors are shown below.</p>

 <p>Note that ACL2 characters always fit into a single byte, which is why we
 can talk about ``bytes''.</p>

 <p>Compared with the usual @(see IO) routines provided by ACL2,
 @('read-file-into-string') is generally much more efficient, and also it does
 not return @(tsee state).  Note that the macroexpansion of a call of this
 macro takes @('state') as an argument; so if you call it in the body of a
 function definition, then &mdash; as usual for functions that take @('state')
 &mdash; either @('(set-state-ok t)') must have been evaluated or else a
 suitable @(':stobjs') declaration, typically @(':stobjs state'), must be
 provided (see @(see xargs)).</p>

 <p>The very large constant @('*read-file-into-string-bound*'), whose
 definition is shown in the final section below, establishes a strict upper
 bound on the size of the string returned.  If the file (or specified portion
 thereof) contains more bytes than this, then @('nil') is returned.</p>

 <h3>Detailed discussion of keyword arguments</h3>

 <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, the entire
 file contents are returned as a string.  In general, @(':start s') specifies
 the part of the file starting at byte position @('s') of the file, and the
 @(':bytes') argument specifies the number of consecutive bytes to be included
 starting at that position: @(':bytes nil') specifies that the rest of the file
 is to be included, while for a natural number @('b'), @(':bytes b') specifies
 that only the next @('b') bytes are to be included &mdash; but, stopping at
 the end of the file if @('b+s') exceeds the length @('L') of the file.  Below
 we call this case that @('b+s>L') the <i>truncation case</i>.</p>

 <p>The @(':close') argument affects handling of the Lisp stream that is
 created for the specified file.  When the value of @(':close') is the default,
 @(':default'), the criterion for closing the stream immediately after the read
 completes is that either @(':bytes') has value @('nil') (the default) or we
 are in the truncation case @('b+s>L') described above.  Once this stream is
 closed, a Lisp error occurs if @('read-file-with-string') is called when
 either @(':start') or @(':bytes') specifies a non-zero value unless the
 file-clock of the state is advanced first by evaluating
 @('(INCREMENT-FILE-CLOCK STATE)').  See @(see state) for a discussion of the
 logical role of the file-clock of the state.</p>

 <p>Here is a typical log showing such an error message from successive reads,
 together with the evaluation of @('(INCREMENT-FILE-CLOCK STATE)') as a remedy.
 The next section, further below, discusses the closing of streams.</p>

 @({
 ACL2 !>(read-file-into-string "tmp.txt")
 "Hello
 world.
 "
 ACL2 !>(read-file-into-string "tmp.txt")

 ***********************************************
 ************ ABORTING from raw Lisp ***********
 ********** (see :DOC raw-lisp-error) **********
 Error:  Apparently READ-FILE-INTO-STRING has previously closed the stream
 that is associated with file
 "tmp.txt".
 Consider evaluating (INCREMENT-FILE-CLOCK STATE).
 See :DOC read-file-into-string.
 While executing: READ-FILE-INTO-STRING2
 ***********************************************

 The message above might explain the error.  If not, and
 if you didn't cause an explicit interrupt (Control-C),
 then it may help to see :DOC raw-lisp-error.

 To enable breaks into the debugger (also see :DOC acl2-customization):
 (SET-DEBUGGER-ENABLE T)
 ACL2 !>(INCREMENT-FILE-CLOCK STATE)
 <state>
 ACL2 !>(read-file-into-string "tmp.txt")
 "Hello
 world.
 "
 ACL2 !>
 })

 <p>The implementation of @('read-file-into-string') advances a pointer with
 each successive read while the stream is open.  An error is signaled when
 attempting to call @('read-file-into-string') with a @(':start') value that
 points to a byte that is not beyond all bytes already read by previous calls
 (unless there is an intervening evaluation of @('(INCREMENT-FILE-CLOCK
 STATE)')).  Here is a sample log to illustrate this point.</p>

 @({
 ACL2 !>(read-file-into-string "tmp.txt" :bytes 3)
 "Hel"
 ACL2 !>(read-file-into-string "tmp.txt" :start 3 :bytes 2)
 "lo"
 ACL2 !>(read-file-into-string "tmp.txt" :start 4)

 ***********************************************
 ************ ABORTING from raw Lisp ***********
 ********** (see :DOC raw-lisp-error) **********
 Error:  The :start value, 4, specified for a call of READ-FILE-INTO-STRING,
 is less than the position 5 immediately after a previous read of file
 "tmp.txt" at the same file-clock.
 Consider evaluating (INCREMENT-FILE-CLOCK STATE).
 See :DOC read-file-into-string.
 While executing: READ-FILE-INTO-STRING2
 ***********************************************
 })

 <h3>Closing streams</h3>

 <p>A call of @('read-file-into-string') on a given filename opens a Lisp
 stream connected to the given file.  ACL2 keeps track of such an association
 of filenames with streams.</p>

 <p>If the stream remains open for numerous calls of
 @('read-file-into-string'), the operating system could eventually complain
 because too many streams are open at the same time.  Recall that if the value
 of @(':bytes') is non-@('nil') (hence, a natural number), then, except in the
 truncation case, the stream remains open.  In such cases may want to specify
 @(':close t') to prevent leaving too many streams open, unless you plan to
 read more bytes from the same file.  If you decide to close the stream later,
 this can be accomplished efficiently without reading any bytes by evaluating
 the following form for your file, @('"<file>"').</p>

 @({
 (read-file-into-string "<file>" :bytes 0 :close t)
 })

 <h3>Logical definitions</h3>

 <p>We close by showing the relevant ACL2 definitions in the logic.  Thus,
 these do not show 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-logical)

 @(def read-file-into-string2)

 @(def read-file-into-string)")
other
(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 cpu-time
 state)'), where @('cpu-time') is the elapsed cpu time in seconds since the
 start of the current ACL2 session and @('state') is the resulting ACL2 @(see
 state).  Thus, @('(read-run-time state)') is, by default, equivalent to
 @('(get-cpu-time state)').  But @('read-run-time') can be made to return
 elapsed real time (wall clock time) instead, thus making it equivalent to
 @('(get-real-time state)').  Note that time is returned in seconds in all of
 these cases.</p>

 <p>To specify that @('read-run-time') shall use cpu time or real time:</p>

 @({
 (assign get-internal-time-as-realtime t)   ; use real time
 (assign get-internal-time-as-realtime nil) ; use cpu time
 })

 <p>See @(see get-internal-time) for more discussion of cpu time vs. real 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 @(see state) by popping the value to
 return from its acl2-oracle field.</p>

 @(def read-run-time)

 <p>Note that logically @('(read-run-time state)'), @('(get-real-time state)'),
 and @('(get-cpu-time state)') are all equal (defined using the acl2-oracle),
 so for example ACL2 succeeds in the proof of @('(thm (equal (get-real-time
 state) (get-cpu-time state)))'), even though the first returns elapsed real
 time and the second returns elapsed cpu time.  However, there is no
 contradiction: either way, we are logically just reading the oracle of
 @('state').  In the ACL2 loop, successive calls of @('(get-real-time state)')
 and @('(get-cpu-time state)') would be operating on different values of
 @('state') (because their oracles differ).</p>")
other
(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 !>

 })")
other
(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 have fetched the @(see community-books), then you will
 already have 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>

<p>ACL2(r) does not currently support the @(see useless-runes) feature.</p>")
other
(defxdoc real-listp
  :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>")
other
(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>")
other
(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)")
other
(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)
 })")
other
(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>")
other
(defxdoc recursion-and-induction
  :parents (documentation acl2 about-acl2)
  :short "Recursion and Induction"
  :long "<h3>Recursion and Induction</h3>

 <h3>Preface and Acknowledgments</h3>

 <p>These notes are for teaching yourself how to prove theorems about
 recursively defined functions using mathematical induction.  Think of this as
 a college-level practical math course that just happens to focus on issues of
 concern in computing.  We assume you're passingly familiar with notions from
 formal mathematical logic, like &ldquo;axioms&rdquo; and &ldquo;rules of
 inference&rdquo; (like instantiation and substitution of equals for equals) to
 derive &ldquo;new&rdquo; truths from &ldquo;old&rdquo; ones.  We describe a
 very simple logical system and present many exercises for you to do.</p>

 <p>Our presentation is less formal than formal logicians would expect, and the
 &ldquo;proofs&rdquo; we expect of you would be considered just &ldquo;proof
 sketches&rdquo; by formal logicians.  But we believe we're precise enough that
 if you follow our rules your &ldquo;proofs&rdquo; could be turned into formal
 proofs in conventional first-order mathematical logic.</p>

 <p>Unlike a traditional course in logic, we do not focus on metatheory but on
 lots of proofs about elementary algorithms expressed recursively.  It helps if
 you're familiar with computer programming because our logic is a subset of the
 programming language Lisp and the exercises involve conjectures about simple
 list processing algorithms like member, union, reverse, etc.  We do not assume
 prior familiarity with Lisp.</p>

 <p>In fact, the logic is a subset of the mechanized logic of the ACL2
 system. ACL2 stands for &ldquo;A Computational Logic for Applicative Common
 Lisp&rdquo; and the ACL2 system includes a programming language and an
 &ldquo;automatic&rdquo; theorem prover.  But this is not a course in
 mechanical theorem proving or how to use ACL2.  In fact, we recommend that you
 not use the ACL2 system while doing these exercises.  A good way to learn to
 use ACL2 &mdash; or any of today's mechanical proof systems &mdash; is to
 learn to do proofs by hand.  It will teach you how to define functions that
 are convenient to analyze, how to state inductively provable theorems, how to
 decompose theorems into simpler &ldquo;lemmas&rdquo;, and how to simplify
 terms using previously proved results.</p>

 <p>If your goal is to learn to prove theorems about recursively defined
 functions, work your way through these notes and do the exercises.  It can
 help if you partner with someone else so you have someone to double-check your
 proofs.  If your goal is learn to use the ACL2 system to prove theorems, we
 recommend that you start exactly the same way: work through these exercises by
 hand (ideally, all of them).  Only then should you fire up the prover and try
 to use it to prove the same theorems you've proved by hand.  It will be
 educational.  The ACL2 system is a <i>very</i> attentive partner.</p>

 <p>Our answers to all the exercises are available in the Answer Key, which may
 be found in the @(see community-books), file
 @('demos/r-and-i-answer-key-log.txt').  We urge you not to refer to the Answer
 Key except as a last resort (and, of course, to check your answers).  That
 file is generated by ACL2 and has a certain amount of unavoidable boilerplate
 in it.  You should read the Lisp comment at the top of the file for
 instructions on how to explore and interpret the file.</p>

 <p>This document started as course notes for <i>CS389R Recursion and
 Induction</i>, in the Department of Computer Science of the University of
 Texas at Austin.  The course was created in 1981 by Robert S. Boyer and J
 Strother Moore.  It has been offered almost every year since 1981, taught by
 Boyer, Moore, or Warren A. Hunt, Jr.  Initially, the course used a subset of
 the logic of the Nqthm theorem prover [0], but around 2000 it was changed to a
 subset of the logic of the ACL2 prover [1,2,4].  (See @(see
 r-and-i-annotated-bibliography) for an annotated bibliography that elaborates
 references in square brackets, such as &ldquo;[0]&rdquo;.)  Mechanical theorem
 proving tools were not taught or used in the course.</p>

 <p>In the early 1980s, when Boyer and Moore co-taught the course, the logic
 was presented in a bare-bones style in a few pages.  Several more pages listed
 problems for the students to work on.  Students were expected to formalize
 concepts and come to the blackboard and present definitions and proofs.  Their
 classmates were expected to question and critique what was being said.  Often
 these classroom discussions just raised new problems that the students
 addressed in subsequent class meetings.</p>

 <p>Over time, the course notes were expanded to include explanations,
 examples, and more problems.  Moore wrote the first version of this ACL2-based
 document in the early 2000s, building on joint work with Matt Kaufmann.  That
 document was edited still further by Kaufmann, Moore, and Hunt after Hunt
 began teaching the course in 2004.  In 2022, Kaufmann converted it from LaTeX
 pdf to the hypertext format of ACL2's online documentation and tied it into
 ACL2's documentation.</p>

 <p>Finally, we thank the many sponsors and supporters of the Nqthm and ACL2
 projects over the last 40 years, as well as the many students who have so
 carefully studied and corrected these notes and the many users of Nqthm and
 ACL2.  See the ACL2 @(see Acknowledgments) page.</p>

 <p>Next: <see topic='@(url r-and-i-introduction)'>Introduction</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-table-of-contents
  :parents (recursion-and-induction)
  :short "Recursion and Induction Table of Contents)"
  :long "<h3>Recursion and Induction Table of Contents</h3>

  <ul>
  <li><see topic='@(url recursion-and-induction)'>Preface and Acknowledgments</see><br/></li>
  <li><see topic='@(url r-and-i-introduction)'>Introduction</see><br/></li>
  <li><see topic='@(url r-and-i-data-types)'>Data Types</see><br/></li>
  <li><see topic='@(url r-and-i-terms)'>Terms</see><br/></li>
  <li><see topic='@(url r-and-i-substitutions)'>Substitutions</see><br/></li>
  <li><see topic='@(url r-and-i-abbreviations-for-terms)'>Abbreviations for Terms</see><br/></li>
  <li><see topic='@(url r-and-i-function-definitions)'>Function Definitions</see><br/></li>
  <li><see topic='@(url r-and-i-axioms)'>Axioms</see><br/></li>
  <li><see topic='@(url r-and-i-terms-as-formulas)'>Terms as Formulas</see><br/></li>
  <li><see topic='@(url r-and-i-definitions-revisited)'>Definitions Revisited</see><br/></li>
  <li><see topic='@(url r-and-i-structural-induction)'>Structural Induction</see><br/></li>
  <li><see topic='@(url r-and-i-arithmetic)'>Arithmetic</see><br/></li>
  <li><see topic='@(url r-and-i-inadequacies-of-structural-recursion)'>Inadequacies of Structural Recursion</see><br/></li>
  <li><see topic='@(url r-and-i-ordinals)'>The Ordinals</see><br/></li>
  <li><see topic='@(url r-and-i-definitional-principle)'>The Definitional Principle</see><br/></li>
  <li><see topic='@(url r-and-i-induction-principle)'>The Induction Principle</see><br/></li>
  <li><see topic='@(url r-and-i-relations-between-recursion-and-induction)'>Relations Between Recursion and Induction</see><br/></li>
  <li><see topic='@(url r-and-i-more-problems)'>More Problems</see><br/></li>
  <li><see topic='@(url r-and-i-more-inadequacies-of-the-definitional-principle)'>More Inadequacies of the Definitional Principle</see><br/></li>
  <li><see topic='@(url r-and-i-still-more-problems)'>Still More Problems</see><br/></li>
  <li><see topic='@(url r-and-i-annotated-bibliography)'>Annotated Bibliography</see><br/></li>
  </ul>
  ")
other
(defxdoc r-and-i-introduction
  :parents (recursion-and-induction)
  :short "Recursion and Induction: Introduction"
  :long "<p>
 The language we will use is a subset of Lisp called ACL2.  ACL2, which stands
 for <i>A Computational Logic for Applicative Common Lisp</i>, is both a
 functional programming language based on Common Lisp and a first-order
 mathematical theory with induction.  There is a mechanical theorem prover for
 ACL2, but we do not discuss it here.  A good way to learn to use that theorem
 prover is first to master the art of recursive definition and inductive proof.
 </p>

 <p>This course on Recursion and Induction uses a tiny fragment of full ACL2.
 We describe just enough formal machinery to study recursion and induction in
 an interesting context.  This document is self-contained.  You'll need nothing
 besides this document, a pencil and paper (or a computer), and time and space
 to think.  In the interest of scholarly completeness, we provide an annotated
 bibliography; see @(see r-and-i-annotated-bibliography).  But none of
 the documents listed there is necessary for the problems here.</p>

 <p>These notes are meant to be read linearly, like a text book.  Each section
 ends with a link to the next section.  For example, the link to the section
 after this one looks like this, <see topic='@(url r-and-i-data-types)'>Data
 Types</see>; but don't go there yet!</p>

 <p>Throughout these notes you will see see links to resources on the web and
 some of those links take you out of the <i>Recursion and Induction</i> notes
 and into ACL2's online manual.  Those &ldquo;external&rdquo; links appear like
 this, &ldquo;(Maybe explore &lt;&lt;&hellip;&gt;&gt;?)&rdquo;.  These links
 lead to related discussions of issues and features of the ACL2 system.  You'll
 need to be connected to the web to access some of these pages, unless you have
 installed ACL2 on your system and built the full manual and books
 documentation.  See the @(see installation) instructions.  We provide this
 material for students who want to explore further.  But these links are
 technically irrelevant to the student who is focused on working the exercises
 here, even if your ultimate goal is to learn how to use ACL2.  First, learn
 how to do the exercises here.  In a second pass, where you're trying to get
 ACL2 to do your proofs, you might want to explore.  And remember, it is easy
 for explorers to get lost!</p>

 <p><b>If you are working your way through <i>Recursion and Induction</i> and
 decide to follow one of these explorer links be sure to use the
 &ldquo;Back&rdquo; feature of your browser to return to these notes.</b></p>

 <p>Next: <see topic='@(url r-and-i-data-types)'>Data Types</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-data-types
  :parents (recursion-and-induction)
  :short "Recursion and Induction: Data Types"
  :long "<p>ACL2 provides five data types: numbers, characters, strings,
 symbols, and ordered pairs.</p>

 <p>Next: <see topic='@(url r-and-i-numbers)'>Numbers</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(order-subtopics r-and-i-data-types
  (r-and-i-numbers r-and-i-characters
    r-and-i-strings
    r-and-i-symbols
    r-and-i-pairs
    r-and-i-identity
    r-and-i-data-types-exercises))
other
(defxdoc r-and-i-numbers
  :parents (r-and-i-data-types)
  :short "Recursion and Induction: Numbers"
  :long "<p>
 The only numbers we will use are the integers, written in the usual way,
 e.g., <tt>-3</tt>, <tt>0</tt>, and <tt>123</tt>.
 ACL2 allows integers to be written in other ways, e.g., <tt>00123</tt>,
 <tt>+123</tt>, <tt>246/2</tt>, <tt>#b1111011</tt>, <tt>#o173</tt> and <tt>#x7B</tt> are
 all ways to write <tt>123</tt>.  However, we will always write them in
 conventional decimal notation.
 </p>

 <p>
 ACL2 also supports rationals, e.g., <tt>1/3</tt> and <tt>22/7</tt>, and complex
 rationals, e.g., <tt>#c(5 2)</tt>, which is more commonly written 5 + 2<i>i</i>.  Lisp, but
 not ACL2, supports floating point numbers, e.g., <tt>3.1415</tt> and
 <tt>31415E-4</tt>.
 </p>

 <p>(Maybe explore &lt;&lt;@(see numbers)&gt;&gt;?)</p>

 <p>Next: <see topic='@(url r-and-i-characters)'>Characters</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-characters
  :parents (r-and-i-data-types)
  :short "Recursion and Induction: Characters"
  :long "<p>
 We will not use character objects in this document.
 In case you come across such an object in your exploration of ACL2,
 some characters are <tt>#\a</tt>, <tt>#\A</tt>, <tt>#\Newline</tt> and
 <tt>#\Space</tt>.  It is actually possible in ACL2 to &ldquo;construct&rdquo; and
 &ldquo;deconstruct&rdquo; characters in terms of naturals.  For example, one can
 construct <tt>#\A</tt> from <tt>65</tt>, the ASCII code for uppercase `A'.
 </p>

 <p>(Maybe explore &lt;&lt;@(see characters)&gt;&gt;?)</p>

 <p>Next: <see topic='@(url r-and-i-strings)'>Strings</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-strings
  :parents (r-and-i-data-types)
  :short "Recursion and Induction: Strings"
  :long "<p>
 Strings in our subset of ACL2 are written as sequences of ASCII characters
 between successive <i>string quotes</i>.  For example, here is a string:
 <tt>"Hello, World!"</tt>.  For the purposes of this document, we will treat
 strings as atomic objects, though it is actually possible to construct and
 deconstruct them in terms of lists of character objects.
 </p>

 <p>(Maybe explore &lt;&lt;@(see strings)&gt;&gt;?)</p>

 <p>Next: <see topic='@(url r-and-i-symbols)'>Symbols</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-symbols
  :parents (r-and-i-data-types)
  :short "Recursion and Induction: Symbols"
  :long "<p>
 Unlike many languages, Lisp provides symbols as primitive data objects.  Some
 example symbols are <tt>t</tt>, <tt>nil</tt>, <tt>LOAD</tt>, <tt>STORE</tt>,
 <tt>ICONST_0</tt>, <tt>prime-factors</tt>, <tt>++</tt>, and <tt>file77</tt>.  For the
 purposes of this document, we will treat symbols as atomic objects, though it
 is actually possible to construct and deconstruct them in terms of strings.
 </p>

 <p>
 For the purposes of this document, a symbol is a sequence of alphabetic
 characters, digits, and/or certain signs (specifically, <tt>+</tt>, <tt>-</tt>,
 <tt>*</tt>, <tt>/</tt>, <tt>=</tt>, <tt>&lt;</tt>, <tt>&gt;</tt>, <tt>?</tt>, <tt>!</tt>, <tt>$</tt>,
 <tt>&amp;</tt>, and <tt>_</tt> (underscore)) that cannot be read as a number.  Case
 is unimportant.  Symbols are parsed to have the greatest length possible
 under the rules above.  Thus, <tt>xy</tt> is one symbol, not two symbols (<tt>x</tt>
 and <tt>y</tt>) written without intervening whitespace!
 </p>

 <p>
 Note that <tt>t</tt> and <tt>T</tt> are different ways to write the same symbol, as
 are <tt>nil</tt>, <tt>Nil</tt>, and <tt>NIL</tt>.  <tt>T</tt> and <tt>nil</tt> are called
 the <i>Boolean symbols</i>.  <tt>T</tt> is frequently used to denote <i>true</i>
 and <tt>nil</tt> is used to denote <i>false</i>.  For reasons that will become
 apparent, <tt>nil</tt> is also used as the <i>empty list</i>.
 </p>

 <p>(Maybe explore &lt;&lt;@(see symbols)&gt;&gt;?)</p>

 <p>Next: <see topic='@(url r-and-i-pairs)'>Pairs</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-pairs
  :parents (r-and-i-data-types)
  :short "Recursion and Induction: Pairs"
  :long "<p>
 Pairs are written in Lisp's <i>dot notation</i>.  Instead of conventional
 Cartesian notation, e.g., &lang; <tt>1</tt>, <tt>2</tt> &rang;, Lisp replaces
 the angle brackets with parentheses and the comma with a dot, <tt>(1 . 2)</tt>.
 Thus, <tt>((1 . 2) . (3 . 4))</tt> is the pair containing the pair <tt>(1 . 2)</tt>
 in its left component and the pair <tt>(3 . 4)</tt> in its right.  In high
 school, you might have written this object as &lang;&lang;1, 2&rang;,&lang;3,
 4&rang;&rang;.  Note that exactly one object must follow the dot; for example,
 the notation <tt>((1 . 2) . 3 4)</tt> is illegal.  However, one or more
 objects may precede the dot, as discussed below.</p>

 <p>
 In Lisp, pairs are called <i>conses</i>.  Non-conses are called <i>atoms</i>.
 The left component is called the <i>car</i>&nbsp; and the right component is called
 the <i>cdr</i>&nbsp; (pronounced &ldquo;cudder&rdquo;).
 (Remark.  The names come from the
 original implementation of Lisp on the IBM 704.  That machine had a 36-bit
 word that was logically divided into two parts, the &ldquo;address&rdquo; and the
 &ldquo;decrement.&rdquo;  Lisp used such words to represent a <tt>cons</tt> cell.  The
 address part pointed to the left component and the decrement part pointed to
 the right component.  Thus, the operations were <tt>car</tt> (&ldquo;contents of
 address of register&rdquo;) and <tt>cdr</tt> (&ldquo;contents of decrement of
 register&rdquo;).)
 Lisp provides three conventions for writing parenthesized
 constants.
 </p>

 <ul>
 <li><tt>Nil</tt> can be written <tt>()</tt>.

 <p/>
 </li>
 <li>A pair of the form <tt>(<i>x</i>&nbsp; . nil)</tt> may be written <tt>(<i>x</i>)</tt>.

 <p/>
 </li>
 <li>A pair of the form <tt>(<i>x</i>&nbsp; . (<i>y</i>&nbsp; &hellip;))</tt> may be written <tt>(<i>x</i>
 <i>y</i>&nbsp; &hellip;)</tt>.
 </li>
 </ul>

 <p>
 Thus, the cons <tt>(1 . (2 . (3 . nil)))</tt> may be written <tt>(1 2 3)</tt>.
 This suggests the most common use of conses: to represent linked lists or
 sequences.  The special role of <tt>nil</tt> in these conventions is the only
 sense in which <tt>nil</tt> is &ldquo;the empty list.&rdquo;
 </p>

 <p>
 Any object can be treated as a list!  If a cons is being treated as a list,
 then its car is the first element and its cdr is treated as a list of the
 remaining elements.  If an atom is treated as a list, it is treated as the
 empty list.  <tt>Nil</tt> is just the most common atom used in this way.
 </p>

 <p>
 Thus, the elements of <tt>(1 . (2 . (3 . nil)))</tt> are <tt>1</tt>, <tt>2</tt>, and
 <tt>3</tt>, respectively.  The length of this list is three.  If <tt>((1 . 2)
 . (3 . 4))</tt> is treated as a list, its elements are <tt>(1 . 2)</tt> and <tt>3</tt>;
 its length is two.  The <tt>4</tt> is just the terminal atom.  <tt>((1 . 2)
 . (3 . nil))</tt> and <tt>((1 . 2) . (3 . 4))</tt> are different objects, but when
 treated as lists they have the same two elements.
 </p>

 <p>
 Here is a list of the symbols naming the summer months: <tt>(June July
 August)</tt>.  It could also be written <tt>(JUNE . (JULY . (AUGUST . NIL)))</tt>
 and many other ways.
 </p>

 <p>(Maybe explore &lt;&lt;@(see conses)&gt;&gt;?)</p>

 <p>Next: <see topic='@(url r-and-i-identity)'>identity</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-identity
  :parents (r-and-i-data-types)
  :short "Recursion and Induction: Identity"
  :long "<p>
 Since a pair can typically be written down in several different ways, you
 might ask how can you tell whether one display is equal to another?  For
 example, how can you determine that <tt>(1 . (2 . (3 . nil)))</tt> is the same
 pair as <tt>(1 2 3)</tt>, which is also the same pair as <tt>(1 . (2 3))</tt>?
 </p>

 <p>
 One way is to write each constant in a canonical form.  If their canonical
 forms are different, the two constants are different.  For integers, the
 standard canonical form is to use base 10 and to drop leading <tt>0</tt>s and
 &ldquo;+&rdquo; signs.  For symbols, it is to write everything in upper case.  For
 conses, the canonical form is to eschew the use of the three conventions
 noted in the previous section and to use dot notation exclusively.
 </p>

 <p>Next: <see topic='@(url r-and-i-data-types-exercises)'>Data Types
 Exercises</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-data-types-exercises
  :parents (r-and-i-data-types)
  :short "Recursion and Induction: Data Types Exercises"
  :long "<p>
 <b>Problem 1. <br/></b> Each of the utterances below is supposed to be a single object.  Say whether
 it is a number, string, symbol, pair, or ill-formed (i.e., does not
 represent a single object in our language).
 </p>

 <ol>
 <li><tt>Monday</tt>
 </li>
 <li><tt><i>&pi;</i></tt>
 </li>
 <li><tt>HelloWorld!</tt>
 </li>
 <li><tt>--1</tt>
 </li>
 <li><tt>-1</tt>
 </li>
 <li><tt>*PI*</tt>
 </li>
 <li><tt>31415x10**-4</tt>
 </li>
 <li><tt>(A . B . C)</tt>
 </li>
 <li><tt>Hello World!</tt>
 </li>
 <li><tt>if</tt>
 </li>
 <li><tt>invokevirtual</tt>
 </li>
 <li><tt>((1) . (2))</tt>
 </li>
 <li><tt>&lt;=</tt>
 </li>
 <li><tt>((A . 1) (B . 2) (C . 3))</tt>
 </li>
 <li><tt>Hello_World!</tt>
 </li>
 <li><tt>+</tt>
 </li>
 <li><tt>lo-part</tt>
 </li>
 <li><tt>31415926535897932384626433832795028841971693993751058209749445923</tt>
 </li>
 <li><tt>(1 . (2 . 3))</tt>
 </li>
 <li><tt>(1 . 2 3)</tt>
 </li>
 <li><tt>"Hello World!" </tt>
 </li>
 <li><tt>((1) (2) . 3)</tt>
 </li>
 <li><tt>()</tt>
 </li>
 </ol>

 <p>
 <b>Problem 2. <br/></b> Group the constants below into equivalence
 classes.  That is, some items below are equal to others even though they are
 displayed differently; group equal constants together.
 </p>

 <ol>
 <li><tt>(1 . (2 3))</tt>
 </li>
 <li><tt>(nil . (nil nil))</tt>
 </li>
 <li><tt>((nil nil) . nil)</tt>
 </li>
 <li><tt>(1 (2 . 3) 4)</tt>
 </li>
 <li><tt>(nil nil)</tt>
 </li>
 <li><tt>(1 (2 . 3) . (4 . ()))</tt>
 </li>
 <li><tt>(HelloWorld !)</tt>
 </li>
 <li><tt>(1 (2 3 . ()) 4)</tt>
 </li>
 <li><tt>((A . t) (B . nil)(C . nil))</tt>
 </li>
 <li><tt>(()())</tt>
 </li>
 <li><tt>(1 2 3)</tt>
 </li>
 <li><tt>(() () . nil)</tt>
 </li>
 <li><tt>(A B C)</tt>
 </li>
 <li><tt>(a . (b . (c)))</tt>
 </li>
 <li><tt>(HELLO WORLD !)</tt>
 </li>
 <li><tt>((a . t) (b) . ((c)))</tt>
 </li>
 </ol>

 <p>Next: <see topic='@(url r-and-i-terms)'>Terms</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-terms
  :parents (recursion-and-induction)
  :short "Recursion and Induction: Terms"
  :long "<p>
 For the purposes of this document, a <i>term</i>&nbsp; is a variable symbol, a
 quoted constant, or a function application written as a sequence,
 enclosed in parentheses, consisting of a function symbol of arity <i>n</i>&nbsp;
 followed by <i>n</i>&nbsp; terms.
 </p>

 <p>

 Since <tt>car</tt> is a function symbol of arity one and <tt>cons</tt> is a
 function symbol of arity two, and <tt>x</tt> and <tt>y</tt> are variable
 symbols, then <tt>(cons (car x) y)</tt> is a term.  In more conventional
 notation this term would be written
 <i>cons</i>&nbsp;(<i>car</i>&nbsp;(<i>x</i>&nbsp;), <i>y</i>&nbsp;).  We call
 <tt>(car x)</tt> and <tt>y</tt> the <i>actual expressions</i>&nbsp; or
 <i>actuals</i>&nbsp; of the <i>function call</i>&nbsp; <tt>(cons (car x)
 y)</tt>.

 </p>

 <p>
 Semantically, terms are interpreted with respect to (i) an assignment binding
 variable symbols to constants and (ii) an interpretation of function symbols as
 mathematical functions.  For example, suppose the variables <tt>x</tt> and
 <tt>y</tt> are bound, respectively, to the constants <tt>1</tt> and <tt>(2 3 4)</tt>,
 and suppose the function symbol <tt>cons</tt> is interpreted as the function
 that constructs ordered pairs (as it always is).  Then the meaning or
 <i>value</i>&nbsp; of the term <tt>(cons x y)</tt> is <tt>(1 . (2 3 4))</tt> or,
 equivalently, <tt>(1 2 3 4)</tt>.  That is, the value of a variable is
 determined by the variable assignment; the value of a quoted constant is
 that constant; and the value of a function application, <tt>(</tt><i>f</i>&nbsp; <i>a_1</i> &nbsp;&hellip;&nbsp;
 <i>a_n</i><tt>)</tt>, is the result of applying the mathematical function assigned to <i>f</i>&nbsp;
 to the values of the actuals, <i>a_i</i>.
 </p>

 <p>
 ACL2 provides an infinite number of <i>variable symbols</i>, whose syntax is
 that of symbols.  Some example variable symbols are <tt>x</tt>, <tt>a1</tt>, and
 <tt>temp</tt>.  The symbols <tt>t</tt> and <tt>nil</tt> are not legal variable symbols.
 </p>

 <p>
 A <i>quoted constant</i>&nbsp; is written by prefixing an integer, a character object, a string, or
 a symbol by a single quote mark.  For example, <tt>'t</tt>, <tt>'nil</tt>, <tt>'-3</tt>, <tt>'</tt><tt>#\A</tt>,
 <tt>'"Hello World!"</tt> and <tt>'LOAD</tt> are quoted constants.
 Note that we do not consider <tt>'(1 2 3)</tt> a quoted constant.  This
 is a mere technicality.  We will shortly introduce some abbreviations
 that allow us to write <tt>'(1 2 3)</tt> as an abbreviation for
 <tt>(cons '1 (cons '2 (cons '3 'nil)))</tt>.
 </p>

 <p>
 ACL2 also has an infinite number of <i>function symbols</i>&nbsp; each of which has
 an associated <i>arity</i>&nbsp; or number of arguments.  For the moment we will
 concern ourselves with six primitive function symbols: <tt>cons</tt>, <tt>car</tt>,
 <tt>cdr</tt>, <tt>consp</tt>, <tt>if</tt>, and <tt>equal</tt>, described below.  Note that
 we implicitly specify the arity of each primitive function symbol.
 </p>

 <dl>
 <dt></dt>
 <dd><tt>(cons <i>x</i> <i>y</i>)</tt> - construct and return the ordered pair <tt>(<i>x</i>
 . <i>y</i>)</tt>.

 <p/>
 </dd>
 <dt></dt>
 <dd><tt>(car <i>x</i>)</tt> - return the left component of <i>x</i>, if <i>x</i>&nbsp; is a pair;
  otherwise, return <tt>nil</tt>.

 <p/>
 </dd>
 <dt></dt>
 <dd><tt>(cdr <i>x</i>)</tt> - return the right component of <i>x</i>, if <i>x</i>&nbsp; is a pair;
  otherwise, return <tt>nil</tt>.

 <p/>
 </dd>
 <dt></dt>
 <dd><tt>(consp <i>x</i>)</tt> - return <tt>t</tt> if <i>x</i>&nbsp; is a pair; otherwise return <tt>nil</tt>.

 <p/>
 </dd>
 <dt></dt>
 <dd><tt>(if <i>x</i> <i>y</i> <i>z</i>)</tt> - return <i>z</i>&nbsp; if <i>x</i>&nbsp; is <tt>nil</tt>; otherwise return <i>y</i>.

 <p/>
 </dd>
 <dt></dt>
 <dd><tt>(equal <i>x</i> <i>y</i>)</tt> - return <tt>t</tt> if <i>x</i>&nbsp; and <i>y</i>&nbsp; are identical;
 otherwise return <tt>nil</tt>.
 </dd>
 </dl>

 <p>
 With these primitives we cannot do anything interesting with
 numbers, characters, strings, and symbols.  They are just tokens to put into or take out
 of pairs.  But we can explore most of the interesting issues in recursion
 and induction in this setting!
 </p>

 <p>(Maybe explore &lt;&lt;@(see term)&gt;&gt;?)</p>

 <p>Note that if the terms <i>&alpha;</i> and <i>&beta;</i> both evaluate to
 the same value, <i>v</i>, then the term <tt>(equal</tt> <i>&alpha;</i>
 <i>&beta;</i><tt>)</tt> evaluates to <tt>t</tt>.  For example, the terms
 <tt>(car (cons '3 '4))</tt> and <tt>'3</tt> both evaluate to the value
 <tt>3</tt>, so the term <tt>(equal (car (cons '3 '4)) '3)</tt> evaluates to
 <tt>t</tt>.</p>

 <p>
 <b>Problem 3. <br/></b> Which of the utterances below are terms?
 </p>

 <ol>
 <li><tt>(car (cdr x))</tt>
 </li>
 <li><tt>(cons (car x y) z)</tt>
 </li>
 <li><tt>(cons 1 2)</tt>
 </li>
 <li><tt>(cons '1 '2)</tt>
 </li>
 <li><tt>(cons one two)</tt>
 </li>
 <li><tt>(cons 'one 'two)</tt>
 </li>
 <li><tt>(equal '1 (car (cons '2 '3)))</tt>
 </li>
 <li><tt>(if t 1 2)</tt>
 </li>
 <li><tt>(if 't '1 '2)</tt>
 </li>
 <li><tt>(car (cons (cdr hi-part) (car lo-part)))</tt>
 </li>
 <li><tt>car(cons x y)</tt>
 </li>
 <li><tt>car(cons(x,y))</tt>
 </li>
 <li><tt>(cons 1 (2 3 4))</tt>
 </li>
 </ol>

 <p>
 <b>Problem 4. <br/></b> For each constant below, write a term whose value is the constant.
 </p>

 <ol>
 <li><tt>((1 . 2) . (3 . 4))</tt>
 </li>
 <li><tt>(1 2 3)</tt>
 </li>
 <li><tt>((1 . t) (2 . nil) (3 . t))</tt>
 </li>
 <li><tt>((A . 1) (B . 2))</tt>
 </li>
 </ol>

 <p>
 <b>Problem 5. <br/></b> For each term below, write the constant to which it evaluates.
 </p>

 <ol>
 <li><tt>(cons (cons '1 '2) (cons (cons '3 '4) 'nil))</tt>
 </li>
 <li><tt>(cons '1 (cons '2 '3))</tt>
 </li>
 <li><tt>(cons 'nil (cons (cons 'nil 'nil) 'nil))</tt>
 </li>
 <li><tt>(if 'nil '1 '2)</tt>
 </li>
 <li><tt>(if '1 '2 '3)</tt>
 </li>
 <li><tt>(equal 'nil (cons 'nil 'nil))</tt>
 </li>
 <li><tt>(equal 'Hello 'HELLO)</tt>
 </li>
 <li><tt>(equal (cons '1 '2) (cons '1 'two))</tt>
 </li>
 </ol>

 <p>Next: <see topic='@(url r-and-i-substitutions)'>Substitutions</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-substitutions
  :parents (recursion-and-induction)
  :short "Recursion and Induction: Substitutions"
  :long "<p>
 A <i>substitution</i>&nbsp; is a set {<i>v_0</i>&nbsp; &larr; <i>t_0</i>, <i>v_1</i>&nbsp; &larr; <i>t_1</i>,&nbsp;
 &hellip;} where each <i>v_i</i>&nbsp; is a distinct variable symbol and each <i>t_i</i>&nbsp; is a term.
 If, for a given substitution <i>&sigma;</i>&nbsp; and variable <i>v</i>, there is an <i>i</i>&nbsp; such
 that <i>v</i>&nbsp; is <i>v_i</i>, we say <i>v</i>&nbsp; <i>is bound</i>&nbsp; by <i>&sigma;</i>.  If <i>v</i>&nbsp; is bound
 by <i>&sigma;</i>, then the <i>binding</i>&nbsp; of <i>v</i>&nbsp; in <i>&sigma;</i>&nbsp; is <i>t_i</i>, for the
 <i>i</i>&nbsp; such that <i>v_i</i>&nbsp; is <i>v</i>.  (In set theory, a substitution is just a finite function
 that maps the <i>v_i</i>&nbsp; to their respective <i>t_i</i>.)
 </p>

 <p>
 The result of <i>applying</i>&nbsp; a substitution <i>&sigma;</i>&nbsp; to a term <i>term</i>&nbsp; is
 denoted <i>term</i>/<i>&sigma;</i>&nbsp; and is defined as follows.  If <i>term</i> is a
 variable, then <i>term</i>/<i>&sigma;</i>&nbsp; is either the binding of <i>term</i>&nbsp; in <i>&sigma;</i>&nbsp; or
 is <i>term</i>&nbsp; itself, depending on whether <i>term</i>&nbsp; is bound in <i>&sigma;</i>.  If
 <i>term</i>&nbsp; is a quoted constant, <i>term</i>/<i>&sigma;</i>&nbsp; is <i>term</i>.  Otherwise, <i>term</i>&nbsp; is
 <tt>(</tt><i>f</i>&nbsp; <i>a_1</i>&nbsp; &nbsp;&hellip;&nbsp; <i>a_n</i><tt>)</tt> and <i>term</i>/<i>&sigma;</i>&nbsp; is <tt>(</tt><i>f</i>&nbsp; <i>a_1</i>/<i>&sigma;</i>&nbsp; &nbsp;&hellip;&nbsp;
 <i>a_n</i>/<i>&sigma;</i><tt>)</tt>.
 </p>

 <p>
 <b>Problem 6. <br/></b> Suppose <i>&sigma;</i>&nbsp; is
 </p>

 <p>
 <code>
 {x &larr; (car a),
  y &larr; (cdr x)}</code>
 </p>

 <p>
 What term is <tt>(car (cons x (cons y (cons '"Hello" z))))</tt>/<i>&sigma;</i>?
 </p>

 <p>Next: <see topic='@(url r-and-i-abbreviations-for-terms)'>Abbreviations for
 Terms</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-abbreviations-for-terms
  :parents (recursion-and-induction)
  :short "Recursion and Induction: Abbreviations for Terms"
  :long "<p>
 Recall that a term is a variable symbol, a quoted constant, or a function
 application written as a sequence, enclosed in parentheses, consisting of a
 function symbol of arity <i>n</i>&nbsp; followed by <i>n</i>&nbsp; terms.
 See <see topic='@(url r-and-i-terms)'>Terms</see>.
 However, we implement certain conventions that allow terms to be abbreviated.
 The conventions allow case to be ignored (when writing symbols), certain
 constants to be written without being quoted, and certain primitive
 functions to be given more arguments than their arity implies.  The ACL2
 implementation also supports a powerful macro facility inherited from Lisp,
 but we do not discuss macros in this course.
 </p>

 <p>
 When input is being read in and parsed into lexical tokens, the characters in
 tokens parsed as Lisp symbols are converted to upper case.  Thus, the
 following are three different ways to type in the same symbol: @('NIL'),
 @('Nil'), and @('nil').  Similarly, @('(cons 'e x)') and @('(Cons 'E x)') are
 both read the same way as @('(CONS 'E X)').  It may seem strange to have
 different ways to write the same symbol but you're very familiar with the
 similar conventions applied to numbers: 123, +123, and 0123 are three
 different ways to write the same integer.  If you wish to type a symbol whose
 name includes lower case characters you must surround the whole symbol with
 vertical bars.  E.g., @('|nil|') is a different symbol than @('nil').  But in
 this course we do not use symbols whose names include lower case characters.
 </p>

 <p>
 The conversion to upper case only happens when parsing symbols.  Strings and
 character objects are not automatically converted to upper case.  Thus,
 @('"NIL"'), @('"Nil"') and @('"nil"') are three different strings, and
 @('#\a') is a different character object than @('#\A').
 </p>

 <p>
 In this document, when we write symbols we generally write them in lower case
 typewriter font, e.g., @('nil'), and we capitalize them when used as the first
 word of a sentence, e.g., @('Nil'). Occasionally we write them in all upper
 case, e.g., @('NIL'), to emphasize that particular symbol or to further
 distinguish the symbol from a nearby English word with the same spelling, as
 in the sentence ``<tt>AND</tt> and <tt>OR</tt> denote conjunction and
 disjunction.''  But regardless of the case we use &mdash; whether lower case,
 captialized, or upper case &mdash; we are referring to the same upper case
 symbol.
 </p>

 <p> The next convention allows you to drop the single quote mark on certain
 constants.  The definition of a term requires constants to be quoted.  E.g.,
 since @('evenp') is a function symbol of arity 1, @('(evenp '3)') is a term
 but @('(evenp 3)') is not because @('3') is neither a variable symbol, a
 <i>quoted</i>&nbsp; constant, or a function application.  But we accept the
 latter as an abbreviation of the former because what else could it mean?  To
 see that ambiguity is lurking if quote marks are dropped, consider @('(member
 'e '(a b c))'), where @('member') is a function symbol of arity 2.  What
 happens if we drop either or both of the quote marks?  Then we might still get
 a term that means something completely different.  Here, the function
 @('member') means ``is the first argument an element of the second?''  </p>

 <ul>

 <li>@('(member 'e '(a b c))'): is the constant symbol @('e') an element of the
 constant list @('(a b c)')? </li>

 <li>@('(member e '(a b c))'): is the value of the variable @('e') an element
 of the constant list @('(a b c)')?</li>

 <li>@('(member 'e (a b c))'): is the constant symbol @('e') an element of the
 list computed by applying the function @('a') to the values of variables
 @('b') and @('c')?</li>

 <li>@('(member e (a b c))'): is the value of the variable @('e') an element of
 the list computed by applying the function @('a') to the values of variables
 @('b') and @('c')?</li>

 </ul>

 <p>
 Meaning changes if quote marks are dropped from symbols and lists.  When
 the symbol @('e') is quoted in a term it denotes the constant @('e'); when
 @('e') is not quoted it is a variable symbol and takes on whatever value that
 variable has been assigned in the environment.  Similarly, when a list is
 quoted it denotes that list constant; when it is not quoted it denotes the
 application of its first element to the values of the other elements.
 </p>

 <p>
 But unquoted numbers, character objects, and strings used as terms cannot be
 confused with variable symbols or function applications, so by convention they
 just abbreviate their own quotations.
 </p>

 <p>
 More precisely, the quote convention for atomic objects is as follows:
 If <i>x</i>&nbsp; is the symbol <tt>T</tt>, the symbol <tt>NIL</tt>, an
 integer, a character object, or a string, and <i>x</i>&nbsp; is used where a
 term is expected, then <i>x</i>&nbsp; abbreviates the quoted constant
 <tt>'</tt><i>x</i>.
 </p>

 <p>
 Next we deal with quoted parenthesized expressions.  In the following, an
 <i>expression</i>&nbsp; is an integer, a character object, a string, a symbol,
 an optionally dotted parenthesized sequence of expressions, or a single quote
 mark followed by an expression.  By <i>optionally dotted parenthesized
 sequence of expressions</i> we mean a parenthesized non-empty sequence of
 expressions, optionally containing a dot (.) between the last two expressions
 in the sequence.  For example &ldquo;<tt>(A 123 B)</tt>&rdquo; and
 &ldquo;<tt>(A 123 . B)</tt>&rdquo; are both optionally dotted parenthesized
 sequences of expressions.  (There's no dot in the first expression; the dot in
 the second one changes the meaning.)
 </p>

 <p>We'll be precise in a moment, but @(''(A 123 B)') is an abbreviation for
 @('(cons 'A (cons '123 (cons 'B 'nil)))'), which could also be written
 @('(cons 'A (cons 123 (cons 'B nil)))').  Meanwhile, @(''(A 123 . B)') is an
 abbreviation for @('(cons 'A (cons '123 'B))') which could also be written
 @('(cons 'A (cons 123 'B))').</p>

 <p>
 More generally, a single quote mark followed by an optionally dotted
 parenthesized sequence of expressions, when used as a term, denotes a
 <tt>cons</tt> term as follows, using these four rules:
 </p>

 <p>
 <i>NULL Rule:</i>&nbsp; If '() is used as a term, it abbreviates <tt>'nil</tt>.
 </p>

 <p>
 <i>Singleton Rule:</i>&nbsp; If <tt>'(<i>x</i>)</tt> is used as a
 term it abbreviates <tt>(cons '<i>x</i>&nbsp; 'nil)</tt>.
 </p>

 <p>
 <i>Dotted Pair Rule:</i>&nbsp; If <tt>'(<i>x</i>&nbsp; . <i>y</i>)</tt> is used
 as a term it abbreviates <tt>(cons '<i>x</i>&nbsp; '<i>y</i>)</tt>.
 </p>

 <p>
 <i>List Rule:</i>&nbsp; If <tt>'(<i>x</i>&nbsp; <i>&alpha;</i>)</tt> is used as a
 term and <i>&alpha;</i>&nbsp; is any non-empty sequence of
 expressions it abbreviates <tt>(cons '<i>x</i>
 '(<i>&alpha;</i>))</tt>.  Note the new pair of parentheses around
 <tt><i>&alpha;</i></tt>.
 </p>

 <p>
 Thus, for example, the rules above mean that if
 <tt>'(A B C)</tt> is used as a term then it denotes
 <tt>(cons 'A '(B C))</tt>, which denotes <tt>(cons 'A
 (cons 'B '(C)))</tt>, which denotes <tt>(cons 'A (cons 'B
 (cons 'C 'nil)))</tt>.
 </p>

 <p>
 If <tt>'(A B . C)</tt> is used as a term it denotes
 <tt>(cons 'A (cons 'B 'C))</tt>.
 </p>

 <p>
 It remains to deal with cases like <tt>'</tt><tt>'A</tt> and
 <tt>'</tt><tt>'(A 'B)</tt> involving nested single quote marks.
 Expressions involving nested single quote marks will not arise in
 this course.  But we specify their meaning for completeness.
 </p>

 <p>
 <i>You may consider the following paragraph and the subsequent example as
 optional!</i>
 </p>

 <p>
 Let <i>&alpha;</i>&nbsp; be an expression that does not start with a single quote mark.
 Consider a sequence of two or more single quote marks followed by <i>&alpha;</i>
 and suppose it is used as a term.  It denotes a <tt>cons</tt> derived as
 follows.  Replace <i>&alpha;</i>&nbsp; and the single quote mark immediately before it
 with <tt>(quote <i>&alpha;</i>)</tt>.  Repeat that replacement until all but the first
 single quote mark remains.  Then apply the four rules above.
 </p>

 <p>
 Thus, <tt>'</tt><tt>'(A 'B)</tt>, when used as a term, denotes the
 term derived by the following sequence of steps
 </p>

 <p>
 <tt>'</tt><tt>'(A 'B)</tt>
 <br/><tt>'(quote (A 'B))</tt>
 <br/><tt>(cons 'quote '((A 'B)))</tt>
 <br/><tt>(cons 'quote (cons '(A 'B) 'nil))</tt>
 <br/><tt>(cons 'quote (cons (cons 'A '('B)) 'nil))</tt>
 <br/><tt>(cons 'quote (cons (cons 'A (cons '</tt><tt>'B 'nil)) 'nil))</tt>
 <br/><tt>(cons 'quote (cons (cons 'A (cons '(quote B) 'nil)) 'nil))</tt>
 <br/><tt>(cons 'quote (cons (cons 'A (cons (cons 'quote '(B)) 'nil)) 'nil))</tt>
 <br/><tt>(cons 'quote (cons (cons 'A (cons (cons 'quote (cons 'B 'nil)) 'nil)) 'nil))</tt>
 <br/>
 </p>

 <p>Note that every occurrence of single quote now marks a quoted constant.</p>

 <p><i>End of optional material.</i></p>

 <p>
 When <tt>(list <i>x_1</i>&nbsp; &nbsp;&hellip;&nbsp;)</tt> is used as a term, it abbreviates
 <tt>(cons <i>x_1</i>&nbsp; (list &nbsp;&hellip;&nbsp;))</tt>.  When <tt>(list)</tt> is used as a term,
 it abbreviates <tt>nil</tt>.  Thus <tt>(list a b c)</tt> abbreviates
 <tt>(cons a (cons b (cons c nil)))</tt>.
 </p>

 <p>

 For the purposes of this course you may imagine that <tt>AND</tt> and
 <tt>OR</tt> are defined as function symbols of two arguments.  But we
 use them as though they were function symbols of varying numbers of argument.
 When <tt>AND</tt> and <tt>OR</tt> are provided more than two arguments it just
 abbreviates the corresponding right-associated nest.  Thus, <tt>(and p q r
 s)</tt>, when used where a term is expected, abbreviates <tt>(and p (and
 q (and r s)))</tt>.  In the actual ACL2 implementation, @('AND') and @('OR')
 are ``macros.''

 </p>

 <p>(Maybe explore term abbreviation in ACL2?  But abbreviation is complicated in
 ACL2 by the presence of a powerful macro facility.  To learn about ACL2 term
 abbreviation, explore &lt;&lt;@(see term)&gt;&gt;, paying special attention to
 &ldquo;untranslated&rdquo; terms.  Maybe also explore &lt;&lt;@(see
 macros)&gt;&gt;.)</p>

 <p>
 <b>Problem 7. <br/></b> Show the term abbreviated by each of the following:
 </p>

 <ol>
 <li><tt>(cons 1 '(2 3))</tt>
 </li>
 <li><tt>(equal "Hello" hello)</tt>
 </li>
 <li><tt>(and (or a1 a2 a3) (or b1 b2 b3) (or c1 c2 c3))</tt>
 </li>
 <li><tt>(equal x '(or a1 a2 a3))</tt>
 </li>
 <li><tt>(cons cons '(cons cons 'cons))</tt>
 </li>
 </ol>

 <p>
 The art of displaying a Lisp term in a way that it can be easily read by a
 person is called <i>pretty printing</i>.  We recommend the following heuristics.
 First, write clearly and count your parentheses.  Second, try never to write
 a single line with more than about 30 non-blank characters on it.
 Third, if a function call will not fit on a line, break it into multiple
 lines, indenting each argument the same amount.
 </p>

 <p>
 Below we show one term pretty printed with successively narrower margins.
 (Note that the display is a term only if <tt>app</tt> is a function symbol of
 arity two.)  We find the second and third lines of the first display below
 excessively long.  Each display shows exactly the same term.  Note how we
 break terms to indent arguments the same amount and how we sometimes slide
 the arguments under the function symbol to save horizontal space.
 Personally, we find the second display below (the one labeled &ldquo;<tt>width
 46</tt>&rdquo;) the easiest to read.  We show the others merely to illustrate how
 more space can be saved when one finds oneself close to the right margin.
 </p>

 <p>
 <code>
 |&lt;---------------------------- width 70 ----------------------------&gt;|

 (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))))

 |&lt;---------------- width 46 ----------------&gt;|

 (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))))

 |&lt;------------ width 38 ------------&gt;|

 (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))))

 |&lt;---------- width 34 ----------&gt;|

 (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))))

 |&lt;------- width 28 -------&gt;|

 (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))))

 |&lt;---- width 23 -----&gt;|

 (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))))
 </code>
 </p>

 <p>Next: <see topic='@(url r-and-i-function-definitions)'>Function
 Definitions</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-function-definitions
  :parents (recursion-and-induction)
  :short "Recursion and Induction: Function Definitions"
  :long "<p>
 To define a function, we use the form <tt>(defun</tt> <i>f</i>&nbsp; (<i>v_1</i>&nbsp;&nbsp;&hellip;&nbsp;&nbsp;<i>v_n</i>)&nbsp;<i>&beta;</i><tt>)</tt> where <i>f</i>&nbsp; is the function symbol being defined, the <i>v_i</i>&nbsp; are the
 formal variables or simply <i>formals</i>, and <i>&beta;</i>&nbsp; is the body of the
 function.
 </p>

 <p>
 Operationally, a definition means that to compute <tt>(</tt><i>f</i>&nbsp; <i>a_1</i>&nbsp; &nbsp;&hellip;&nbsp;
 <i>a_n</i><tt>)</tt> one can evaluate the actuals, <i>a_i</i>, bind the formals, <i>v_i</i>&nbsp;, to those
 values, and compute <i>&beta;</i>&nbsp; instead.  Logically speaking, a definition adds
 the axiom that <tt>(</tt><i>f</i>&nbsp; <i>v_1</i>&nbsp; &nbsp;&hellip;&nbsp; <i>v_n</i><tt>)</tt> is equal to <i>&beta;</i>.
 </p>

 <p>
 Here are the Lisp definitions of the standard propositional logic connectives:
 <code>
 (defun not (p) (if p nil t))

 (defun and (p q) (if p q nil))

 (defun or (p q) (if p p q))

 (defun implies (p q) (if p (if q t nil) t))

 (defun iff (p q) (and (implies p q) (implies q p)))
 </code>
 </p>
 <p>
 Note that in Lisp, <tt>and</tt> and <tt>or</tt> are not Boolean valued.  E.g.,
 <tt>(and t 3)</tt> and <tt>(or nil 3)</tt> both return <tt>3</tt>.  This is
 unimportant if they are only used propositionally, e.g., <tt>(and t 3)</tt>
 &harr; <tt>(and 3 t)</tt> &harr; <tt>t</tt>, if
 &ldquo;&harr;&rdquo; means <tt>iff</tt>.  In Lisp, any non-nil value is
 propositionally equivalent to <tt>t</tt>.
 </p>

 <p>
 Here is a recursive definition that copies a <tt>cons</tt>-structure.
 <code>
 (defun tree-copy (x)
   (if (consp x)
       (cons (tree-copy (car x))
             (tree-copy (cdr x)))
       x))
 </code>
 </p>
 <p>
 For example, the term <tt>(tree-copy '((1 . 2) . 3))</tt> has the value <tt>((1
 . 2) . 3)</tt>.
 </p>

<p>(Maybe explore &lt;&lt;@(tsee defun)&gt;&gt;?  Be advised, however, that ACL2's
Definitional Principle imposes restrictions that may not make sense just yet.)</p>

 <p>
 In the exercises below you may wish to define auxiliary (&ldquo;helper&rdquo;)
 functions as part of your solutions.
 </p>

 <p>
 <b>Problem 8. <br/></b> Define <tt>app</tt> to concatenate two lists.  For example
 <tt>(app '(1 2 3) '(4 5 6))</tt> evaluates to <tt>(1 2 3 4 5 6)</tt>.
 </p>

 <p>
 <b>Problem 9. <br/></b> Define <tt>rev</tt> to reverse a list.  For example,
 <tt>(rev '(1 2 3))</tt> evaluates to <tt>(3 2 1)</tt>.
 </p>

 <p>
 <b>Problem 10. <br/></b> Define <tt>mapnil</tt> to &ldquo;copy&rdquo; a list, replacing each element by <tt>nil</tt>.
 Thus, <tt>(mapnil '(1 2 3))</tt> evaluates to <tt>(nil nil nil)</tt>.
 </p>

 <p>
 <b>Problem 11. <br/></b> The result of &ldquo;swapping&rdquo; the pair <tt>(<i>x</i>&nbsp; . <i>y</i>)</tt> is
 the pair <tt>(<i>y</i>&nbsp; . <i>x</i>)</tt>.  Define <tt>swap-tree</tt> to swap every
 cons in a binary tree.  Thus, <tt>(swap-tree '((1 . 2) . (3 . 4)))</tt>
 evaluates to <tt>((4 . 3) . (2 . 1))</tt>.
 </p>

 <p>
 <b>Problem 12. <br/></b> Define <tt>mem</tt> to take two arguments and determine if the first one
 occurs as an element of the second.  Thus, <tt>(mem '2 '(1 2 3))</tt> evaluates to
 <tt>t</tt> and <tt>(mem '4 '(1 2 3))</tt> evaluates to <tt>nil</tt>.
 </p>

 <p>
 <b>Problem 13. <br/></b> Define the list analogue of subset, i.e., <tt>(sub x y)</tt>
 returns <tt>t</tt> or <tt>nil</tt> according to whether every element of <tt>x</tt> is
 an element of <tt>y</tt>.
 </p>

 <p>
 <b>Problem 14. <br/></b> Define <tt>int</tt> to take two lists and to
 return the list of elements that appear in both.  Thus
 <tt>(int '(1 2 3 4) '(2 4 6))</tt> evaluates to <tt>(2 4)</tt>.
 </p>

 <p>
 <b>Problem 15. <br/></b> Define <tt>(tip e x)</tt> to determine whether <tt>e</tt> occurs as a tip
 of the binary tree <tt>x</tt>.
 </p>

 <p>
 <b>Problem 16. <br/></b> Define <tt>(flatten x)</tt> to make a list containing the tips of the binary tree
 <tt>x</tt>.  Thus, <tt>(flatten '((1 . 2) . (3 . 4)))</tt> evaluates to
 <tt>(1 2 3 4)</tt>.
 </p>

 <p>
 <b>Problem 17. <br/></b> Define <tt>evenlen</tt> to recognize lists of even length.  Thus, <tt>(evenlen
 '(1 2 3))</tt> evaluates to <tt>nil</tt> and <tt>(evenlen '(1 2 3 4))</tt> evaluates to <tt>t</tt>.
 </p>

 <p>Next: <see topic='@(url r-and-i-axioms)'>Axioms</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-axioms
  :parents (recursion-and-induction)
  :short "Recursion and Induction: Axioms"
  :long "<p>
 A formal mathematical theory is given by a formal syntax for <i>formulas</i>, a
 set of formulas designated as <i>axioms</i>, and some formula manipulation
 <i>rules of inference</i>
 that allow one to derive <i>new</i> formulas from <i>old</i> ones.  A <i>proof</i>&nbsp; of
 a formula <i>p</i>&nbsp; is a derivation of <i>p</i>&nbsp; from the given axioms using the given
 rules of inference.  If a formula can be proved, it is said to be a
 <i>theorem</i>.  Formulas are given <i>semantics</i> similar to those described for
 terms.  Given an <i>assignment</i> of values to variable symbols and an
 interpretation of the function symbols, every formula is given a truthvalue
 by the semantics.  Given an interpretation, a formula is <i>valid</i> if it is
 given the value true under every possible assignment to the variable symbols.
 A <i>model</i> of a theory is an interpretation that makes all the axioms valid.
 Provided the rules of inference are validity preserving, every theorem is
 valid, i.e., <i>always true</i>.
 </p>

 <p>
 We assume you know all that, and won't go into it further.  The whole point
 of a practical formal theory is to use proof to determine truth: one way to
 determine if a formula is true is to prove it.
 </p>

 <p>
 If <i>&alpha;</i>&nbsp; and <i>&beta;</i>&nbsp; are terms, then <i>&alpha;</i>&nbsp; = <i>&beta;</i>&nbsp; is a
 <i>formula</i>.  If <i>p</i>&nbsp; and <i>q</i>&nbsp; are formulas, then each of the
 following is a formula:
 </p>

 <ul>
 <li><i>p</i> &rarr; <i>q</i>
 </li>
 <li><i>p</i> &and; <i>q</i>
 </li>
 <li><i>p</i> &or; <i>q</i>
 </li>
 <li>&not;<i>p</i>
 </li>
 <li><i>p</i> &harr; <i>q</i>.
 </li>
 </ul>

 <p>
 If <i>&alpha;</i>&nbsp; and <i>&beta;</i>&nbsp; are terms, then <i>&alpha;</i>
 &ne; <i>&beta;</i>&nbsp; is just an
 abbreviation for the formula &not;(<i>&alpha;</i>&nbsp; = <i>&beta;</i>).
 </p>

 <p>
 We extend the notation <i>term</i>/<i>&sigma;</i>&nbsp; in the obvious way so that we can apply
 substitution <i>&sigma;</i>&nbsp; to formulas, replacing all the variables bound by
 <i>&sigma;</i>&nbsp; in all the terms of the formula.
 </p>

 <p>
 The axioms we will use for the initial part of our study are given below.
 Note that Axioms 1 and 8 are actually axiom schemas, i.e., they describe
 an infinite number of axioms.
 </p>

 <p>
 <table class="PAD " style="">
 <tr><td class="LEFT"><b>Axiom</b></td>
 <td class="RIGHT"><b>1.</b></td>
 <td class="LEFT"><tt>'</tt><i>&alpha;</i>&nbsp; &ne; <tt>'</tt><i>&beta;</i>,</td>
 </tr>
 <tr><td class="LEFT">&nbsp;</td>
 <td class="RIGHT">&nbsp;</td>
 <td class="LEFT">where <i>&alpha;</i>&nbsp; and <i>&beta;</i>&nbsp; are distinct integers, characters, strings, or symbols</td>
 </tr>
 <tr><td class="LEFT"><b>Axiom</b></td>
 <td class="RIGHT"><b>2.</b></td>
 <td class="LEFT"><tt>x</tt> &ne; <tt>nil</tt> &rarr; <tt>(if x y z)</tt> = <tt>y</tt></td>
 </tr>
 <tr><td class="LEFT"><b>Axiom</b></td>
 <td class="RIGHT"><b>3.</b></td>
 <td class="LEFT"><tt>x</tt> = <tt>nil</tt> &rarr; <tt>(if x y z)</tt> = <tt>z</tt></td>
 </tr>
 <tr><td class="LEFT"><b>Axiom</b></td>
 <td class="RIGHT"><b>4.</b></td>
 <td class="LEFT"><tt>(equal x y)</tt> = <tt>nil</tt> &or; <tt>(equal x y)</tt> = <tt>t</tt></td>
 </tr>
 <tr><td class="LEFT"><b>Axiom</b></td>
 <td class="RIGHT"><b>5.</b></td>
 <td class="LEFT"><tt>x</tt> = <tt>y</tt> &harr; <tt>(equal x y)</tt> = <tt>t</tt></td>
 </tr>
 <tr><td class="LEFT"><b>Axiom</b></td>
 <td class="RIGHT"><b>6.</b></td>
 <td class="LEFT"><tt>(consp x)</tt> = <tt>nil</tt> &or; <tt>(consp x)</tt> = <tt>t</tt></td>
 </tr>
 <tr><td class="LEFT"><b>Axiom</b></td>
 <td class="RIGHT"><b>7.</b></td>
 <td class="LEFT"><tt>(consp (cons x y))</tt> = <tt>t</tt></td>
 </tr>
 <tr><td class="LEFT"><b>Axiom</b></td>
 <td class="RIGHT"><b>8.</b></td>
 <td class="LEFT"><tt>(consp '</tt><i>&alpha;</i><tt>)</tt> = <tt>nil</tt>,</td>
 </tr>
 <tr><td class="LEFT">&nbsp;</td>
 <td class="RIGHT">&nbsp;</td>
 <td class="LEFT">where <i>&alpha;</i>&nbsp; is an integer, character, string, or symbol</td>
 </tr>
 <tr><td class="LEFT"><b>Axiom</b></td>
 <td class="RIGHT"><b>9.</b></td>
 <td class="LEFT"><tt>(car (cons x y))</tt> = <tt>x</tt></td>
 </tr>
 <tr><td class="LEFT"><b>Axiom</b></td>
 <td class="RIGHT"><b>10.</b></td>
 <td class="LEFT"><tt>(cdr (cons x y))</tt> = <tt>y</tt></td>
 </tr>
 <tr><td class="LEFT"><b>Axiom</b></td>
 <td class="RIGHT"><b>11.</b></td>
 <td class="LEFT"><tt>(consp x)</tt> = <tt>t</tt> &rarr; <tt>(cons (car x) (cdr x))</tt> = <tt>x</tt></td>
 </tr>
 <tr><td class="LEFT"><b>Axiom</b></td>
 <td class="RIGHT"><b>12.</b></td>
 <td class="LEFT"><tt>(consp x)</tt> = <tt>nil</tt> &rarr; <tt>(car x)</tt> = <tt>nil</tt></td>
 </tr>
 <tr><td class="LEFT"><b>Axiom</b></td>
 <td class="RIGHT"><b>13.</b></td>
 <td class="LEFT"><tt>(consp x)</tt> = <tt>nil</tt> &rarr; <tt>(cdr x)</tt> = <tt>nil</tt></td>
 </tr>
 </table>
 </p>

 <p>
 <br/>
 <br/>
 </p>

 <p>
 One axiom described by Axiom (schema) 1 is <tt>'t</tt> &ne; <tt>'nil</tt>.  Others
 are <tt>'nil</tt> &ne; <tt>'3</tt> and <tt>'"Hello"</tt> &ne; <tt>'Hello</tt>.
 We refer to all of these as Axiom 1.
 </p>

 <p>
 One axiom described by Axiom (schema) 8 is <tt>(consp 'nil)</tt> = <tt>nil</tt>.
 Others are <tt>(consp '3)</tt> = <tt>nil</tt> and <tt>(consp 'Hello)</tt> =
 <tt>nil</tt>.  We refer to all of these as Axiom 8.
 </p>

 <p>
 Note that if <i>&phi;</i>&nbsp; is an axiom or theorem and <i>&sigma;</i>&nbsp; is a substitution,
 then <i>&phi;</i>/<i>&sigma;</i>&nbsp; is a theorem, by the Rule of Instantiation.
 </p>

 <p>
 We assume you are familiar with the rules of inference for propositional
 calculus and for equality.  For example, we take for granted that you can
 recognize simple propositional tautologies, reason by cases, and substitute
 equals for equals.
 </p>

 <p>
 For example, we show a theorem below that you should be able to
 prove, using nothing but your knowledge of propositional calculus
 and equality (and Axiom 1).
 </p>

 <p>
 The proof shown below uses the Deduction Law of propositional calculus: we can
 prove <i>p</i> &rarr; <i>q</i>&nbsp; by assuming <i>p</i>&nbsp; as a
 &ldquo;Given&rdquo; and deriving <i>q</i>.
 </p>

 <p>
 <code>
 <b>Theorem.</b>
 (consp x) = t &and; x = (car z) &rarr; (consp (car z)) &ne; nil

 <b>Proof.</b></code>
 </p>

 <p>
 <table class="PAD " style="">
 <tr><td class="RIGHT">1.</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT"><tt>(consp x) = t</tt></td>
 <td align="LEFT">&nbsp;</td><td class="LEFT"><i>{Given}</i></td>
 </tr>
 <tr><td class="RIGHT">2.</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT"><tt>x = (car z)</tt></td>
 <td align="LEFT">&nbsp;</td><td class="LEFT"><i>{Given}</i></td>
 </tr>
 <tr><td class="RIGHT">3.</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT"><tt>t &ne; nil</tt></td>
 <td align="LEFT">&nbsp;</td><td class="LEFT"><i>{Axiom 1}</i></td>
 </tr>
 <tr><td class="RIGHT">4.</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT"><tt>(consp x) &ne; nil</tt></td>
 <td align="LEFT">&nbsp;</td><td class="LEFT"><i>{Equality Substitution, line 1 into line 3}</i></td>
 </tr>
 <tr><td class="RIGHT">5.</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT"><tt>(consp (car z)) &ne; nil</tt></td>
 <td align="LEFT">&nbsp;</td><td class="LEFT"><i>{Equality Substitution, line 2 into line 4}</i></td>
 </tr>
 <tr><td class="RIGHT">&nbsp;</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">Q.E.D.</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">&nbsp;</td>
 </tr>
 </table>
 </p>

 <p>
 We will not write proofs in this style.  We will simply say that
 the formula is a theorem &ldquo;by propositional calculus, equality, and Axiom
 1.&rdquo;
 </p>

 <p>
 Recall that each function definition adds an axiom.  The definition
 <code>
 (defun tree-copy (x)
   (if (consp x)
       (cons (tree-copy (car x))
             (tree-copy (cdr x)))
       x))
 </code>
 </p>
 <p>
 adds the axiom
 <code>
 <b>Axiom</b> tree-copy
 (tree-copy x)
 =
 (if (consp x)
     (cons (tree-copy (car x))
           (tree-copy (cdr x)))
     x)</code>
 </p>

 <p>
 Thus, by the Rule of Instantiation
 <code>
 <b>Theorem.</b>
 (tree-copy (cons a b))
 =
 (if (consp (cons a b))
     (cons (tree-copy (car (cons a b)))
           (tree-copy (cdr (cons a b))))
     (cons a b))</code>
 </p>

 <p>Next: <see topic='@(url r-and-i-terms-as-formulas)'>Terms as
 Formulas</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-terms-as-formulas
  :parents (recursion-and-induction)
  :short "Recursion and Induction: Terms as Formulas"
  :long "<p>
 Logicians typically make a careful distinction between terms (whose values range over
 objects in the domain, like the integers, etc.) and formulas (whose values
 range over the truthvalues).  We have set up two systems of propositional
 calculus.  At the level of formulas we have the traditional equality
 relation, =, and the logical operators
 &and;, &or;, &not;, &rarr;, and &harr;.
 At the level of terms, we have the primitive function
 <tt>equal</tt> and the defined propositional functions <tt>and</tt>, <tt>or</tt>,
 <tt>not</tt>, <tt>implies</tt>, and <tt>iff</tt>.  In our term-level propositional
 calculus, <tt>t</tt> and <tt>nil</tt> play the role of truthvalues.  Because terms
 can be written entirely with ASCII symbols (and easily entered on a
 keyboard!) we tend to write terms and use them as formulas.
 </p>

 <p>
 For example, we might say that
 <code>
 (implies (and (consp x)
               (not (consp y)))
          (not (equal x y)))</code>
 </p>

 <p>
 is a theorem, or even say</p>

<code>
  ((consp x) &and; &not;(consp y))
&rarr;
  x &ne; y
</code>

<p>is a theorem.</p>

<p>But of course, the former cannot be a theorem because it is a term and only
formulas are theorems, and the latter cannot be a theorem because it is not
even a well-formed formula (it uses some terms as though they were
formulas).</p>

 <p>
 If we use an ACL2 term <tt>p</tt> as though it were a formula then the term
 should be understood as an abbreviation for the formula <tt>p</tt> &ne;
 <tt>nil</tt>.  Thus, if we say term <tt>p</tt> is a theorem we mean it is a
 theorem that <tt>p</tt> is not <tt>nil</tt>.
 </p>

 <p>
 Since we assume the reader here is familiar with programming, we assume this
 isomorphism between one syntactic category and another is very familiar.  If
 this makes sense to you, we suggest you just skip the rest of this section,
 including the problems below, and go to <see topic='@(url
 r-and-i-definitions-revisited)'>Definitions Revisited</see>.  But if not, read
 on.
 </p>

<p>This abuse of terminology is justified by the following theorems.</p>

 <p>
 <b>Theorem.</b> <tt>NOT</tt> is Logical Negation:
 <br/><tt>(not p)</tt> &ne; <tt>nil</tt> &harr; &not; (<tt>p</tt> &ne; <tt>nil</tt>).
 </p>

 <p>
 <b>Proof.</b>  We handle the two directions of the &harr;.
 </p>

 <p>
 Case 1.
 <br/><tt>(not p)</tt> &ne; <tt>nil</tt> &rarr; &not; (<tt>p</tt> &ne; <tt>nil</tt>).
 </p>

 <p>
 This is equivalent to its contrapositive:
 </p>

 <p>
 <tt>p</tt> &ne; <tt>nil</tt> &rarr; <tt>(not p)</tt> = <tt>nil</tt>.
 </p>

 <p>
 By the definition of <tt>not</tt> and Axiom 2 and the hypothesis <tt>p</tt>&ne;
 <tt>nil</tt>, <tt>(not p)</tt> = <tt>(if p nil t)</tt> = <tt>nil</tt>.
 </p>

 <p>
 Case 2.
 <br/>&not; (<tt>p</tt> &ne; <tt>nil</tt>) &rarr; <tt>(not p)</tt> &ne; <tt>nil</tt>.
 </p>

 <p>
 The hypothesis is propositionally equivalent to <tt>p</tt> = <tt>nil</tt>.  By
 substitution of equals for equals, the conclusion is <tt>(not nil)</tt> &ne;
 <tt>nil</tt>.  By the definition of <tt>not</tt> and Axioms 3 and 1, <tt>(not
 nil)</tt> = <tt>(if nil nil t)</tt> = <tt>t</tt> &ne; <tt>nil</tt>.
 </p>

 <p>
 Q.E.D.
 </p>

 <p>
 <b>Problem 18. <br/></b> Prove
 <br/><tt>(and p q)</tt> &ne; <tt>nil</tt> &harr; (<tt>p</tt> &ne; <tt>nil</tt>) &and; (<tt>q</tt> &ne; <tt>nil</tt>).
 </p>

 <p>
 <b>Problem 19. <br/></b> Prove
 <br/><tt>(or p q)</tt> &ne; <tt>nil</tt> &harr; (<tt>p</tt> &ne; <tt>nil</tt>) &or; (<tt>q</tt> &ne; <tt>nil</tt>).
 </p>

 <p>
 <b>Problem 20. <br/></b> Prove
 <br/><tt>(implies p q)</tt> &ne; <tt>nil</tt> &harr; (<tt>p</tt> &ne; <tt>nil</tt>) &rarr; (<tt>q</tt> &ne; <tt>nil</tt>).
 </p>

 <p>
 <b>Problem 21. <br/></b> Prove
 <br/><tt>(iff p q)</tt> &ne; <tt>nil</tt> &harr; (<tt>p</tt> &ne; <tt>nil</tt>) &harr; (<tt>q</tt> &ne; <tt>nil</tt>).
 </p>

 <p>
 <b>Problem 22. <br/></b> Prove
 <br/><tt>(equal x y)</tt> &ne; <tt>nil</tt> &harr; (<tt>x</tt> = <tt>y</tt>)
 </p>

 <p>
 Note that these theorems allow us to change the propositional functions to
 their logical counterparts as we move the &ldquo;&ne; <tt>nil</tt>&rdquo; into the term.
 Furthermore, we can always drop a &ldquo;&ne; <tt>nil</tt>&rdquo; anywhere it occurs in a
 formula since the term with which it appears would then be used as a formula
 and would mean the same thing.
 </p>

 <p>
 <b>Problem 23. <br/></b> Using the theorems above, prove that
 <code>
 (implies (and p (implies q r))
          s)
 </code>
 </p>
 <p>
 is equivalent to
 </p>

 <p>
 <tt>
 (p&nbsp;&and;&nbsp;(q&nbsp;&rarr;&nbsp;r))&nbsp;&rarr;&nbsp;s
 </tt>
 </p>

 <p>
 which is equivalent to
 </p>

 <p>
 <code>
  ((p &and; &not; q) &rarr; s)
 &and;
  ((p &and; q &and; r) &rarr; s)</code>
 </p>

 <p>
 When writing proofs on paper or the board, we tend to use formulas and the
 short symbols =, &and;, &or;, &not;, &rarr;, &harr;
 instead of the longer term notation.
 </p>

 <p>
 <b>Problem 24. <br/></b> Prove
 <code>
 (equal (car (if a b c)) (if a (car b) (car c)))
 </code>
 </p>
 <p>
 that is, prove
 <tt>
 (car&nbsp;(if&nbsp;a&nbsp;b&nbsp;c))&nbsp;=&nbsp;(if&nbsp;a&nbsp;(car&nbsp;b)&nbsp;(car&nbsp;c))
 </tt>
 </p>

 <p>
 <b>Problem 25. <br/></b> Prove
 <code>
 (equal (if (if a b c) x y)
        (if a (if b x y) (if c x y)))
 </code>
 </p>

 <p>
 <b>Problem 26. <br/></b> Prove
 <code>
 (equal (tree-copy (cons a b))
        (cons (tree-copy a) (tree-copy b)))
 </code>
 </p>

 <p>Next: <see topic='@(url r-and-i-definitions-revisited)'>Definitions
 Revisited</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-definitions-revisited
  :parents (recursion-and-induction)
  :short "Recursion and Induction: Definitions Revisited"
  :long "<p>
 <b>Problem 27. <br/></b> Suppose we define
 <code>
 (defun f (x) 1)
 </code>
 </p>
 <p>
 and then prove some theorems and then &ldquo;redefine&rdquo; <tt>f</tt> with
 <code>
 (defun f (x) 2)
 </code>
 </p>

 <p> Now prove that @('(equal 'June' 'July)'), using the theorems that
 @('(equal (f x) 1)'), proved before redefining @('f'), and @('(equal (f x)
 2)'), proved after.</p>

 <p>Flesh out your argument using axioms presented earlier (see @(see
 r-and-i-axioms) and see @(see r-and-i-definitions-revisited)).</p>

 <p>A consequence is that since anything provable is valid, then the formula
 <tt>(equal 'June 'July) &ne; nil</tt> is true, hence @(''June') = @(''July'),
 a contradiction!  In the following Problems we explore further such
 consequences of permitting &ldquo;bad&rdquo; definitions.</p>

 <p>
 <b>Problem 28. <br/></b> Suppose we define
 <code>
 (defun f (x) (cons x y))
 </code>
 </p>
 <p>
 Prove <tt>(equal 1 2)</tt>.
 (Remark.  The definition <tt>f</tt> in this problem
 has nothing to do with the definition of <tt>f</tt> in the previous problem!
 We tend to &ldquo;re-use&rdquo; function names like <tt>f</tt>, <tt>g</tt> and <tt>h</tt>
 from time to time simply to avoid inventing new names.)
 </p>

 <p>
 <b>Problem 29. <br/></b> Suppose we define
 <code>
 (defun f (x) (not (f x)))
 </code>
 </p>
 <p>
 Prove <tt>(equal t nil)</tt>.
 </p>

 <p> These problems should disturb you!  We often think of
 &ldquo;definitions&rdquo; as being logically innocuous, allowing us to
 abbreviate complicated expressions.  And we think of proof as a way to
 determine truth.  So it is disturbing if after making a &ldquo;definition&rdquo;
 we are suddenly able to prove things we know aren't true, like that @('June')
 is @('July') or that @('t') is @('nil')!  Something has gone terribly wrong.
 </p>

 <p>
 To prevent this kind of logical inconsistency, we impose some restrictions
 on our ability to introduce definitions.  The restrictions we'll impose will
 prevent us from defining many useful functions but guarantee that we don't
 ruin the logic with &ldquo;definitions&rdquo; like those shown above.  ACL2 is
 much more generous in its restrictions but they are spiritually similar: both
 here and in ACL2 the restrictions on definitions will guarantee that every
 defined function terminates.  We do not explain in this document why
 termination is enough to avoid inconsistencies.</p>

 <p>
 One way to make sure a function terminates is to insist that there is an
 argument that is being <tt>car</tt>'d and/or <tt>cdr</tt>'d at least once every
 time the function recurs and that before it recurs the definition tests that
 the argument is a <tt>cons</tt>-pair.  For example, <tt>(defun f (x) (not (f
     x)))</tt> is disallowed by this restriction, and so is <tt>(defun f (x)
     (not (f (cdr x))))</tt>.  But
 <code>
 (defun f (x)
   (if (consp x)
       (and (not (f (car x)))
            (not (f (cdr (cdr x)))))
       t))
 </code>
 </p>
 <p>
 is allowed because <tt>x</tt> is <tt>car</tt>'d and/or <tt>cdr</tt>'d in every
 recursion and the function tests <tt>(consp x)</tt> before recurring.  We say
 <tt>(consp x)</tt> &ldquo;rules&rdquo; the two recursive calls above.
 </p>

 <p>
 So we have to define the notions of a &ldquo;<tt>car</tt>/<tt>cdr</tt>&rdquo; nest and
 what terms &ldquo;rule&rdquo; the recursive calls.
 </p>

 <p>
 A <i>car/cdr nest around</i>&nbsp; <i>v</i>&nbsp; is <tt>(car</tt> <i>v</i><tt>)</tt>, <tt>(cdr</tt> <i>v</i><tt>)</tt>, or a
 <tt>car</tt>/<tt>cdr</tt> nest around <tt>(car</tt> <i>v</i><tt>)</tt> or <tt>(cdr</tt> <i>v</i><tt>)</tt>.
 Thus, <tt>(car (cdr (car x)))</tt> is a <tt>car</tt>/<tt>cdr</tt> nest around <tt>x</tt>.
 </p>

 <p>
 The idea in this next definition is to take a term <i>&beta;</i>&nbsp; and a particular
 occurrence <i>r</i>&nbsp; of some subterm in <i>&beta;</i>&nbsp; and define the set of tests that
 rule <i>r</i>.  Then, if you have a function definition like <tt>(defun</tt>
 <i>f</i>&nbsp; <tt>(</tt><i>v_1</i>&nbsp;&hellip;&nbsp;<i>v_k</i><tt>)</tt> <i>&beta;</i><tt>)</tt> you can let <i>r</i>&nbsp; be a particular recursive
 call of <i>f</i>&nbsp; in <i>&beta;</i>&nbsp; and then determine which tests rule that call.
 </p>

 <p>
 The <i>rulers</i>&nbsp; of an occurrence of a term <i>r</i>&nbsp; in another term <i>&beta;</i>&nbsp; is
 the set defined as follows:
 </p>

 <ol>
 <li>if <i>&beta;</i>&nbsp; is <tt>(if</tt> <i>p</i> <i>x</i> <i>y</i><tt>)</tt> and <i>r</i>&nbsp; is in <i>x</i>, then
 the rulers of <i>r</i>&nbsp; in <i>&beta;</i>&nbsp; is the set obtained by adding <i>p</i>&nbsp; to the set of
 rulers of <i>r</i>&nbsp; in <i>x</i>;

 <p/>
 </li>
 <li>if <i>&beta;</i>&nbsp; is <tt>(if</tt> <i>p</i> <i>x</i> <i>y</i><tt>)</tt> and <i>r</i>&nbsp; is in <i>y</i>, then
 the rulers of <i>r</i>&nbsp; in <i>&beta;</i>&nbsp; is the set obtained by adding <tt>(NOT</tt> <i>p</i><tt>)</tt> to the set of
 rulers of <i>r</i>&nbsp; in <i>y</i>;

 <p/>
 </li>
 <li>otherwise, the rulers of <i>r</i>&nbsp; in <i>&beta;</i>&nbsp; is the empty set.
 </li>
 </ol>

 <p>
 Thus, in the term <tt>(if a (if b (h c) (h d)) (g c))</tt>, both <tt>a</tt> and
 <tt>b</tt> rule the first occurrence of <tt>c</tt> and the occurrence of <tt>(h
 c)</tt>.  In addition, <tt>a</tt> and <tt>(not b)</tt> rule the occurrences of <tt>d</tt> and <tt>(h d)</tt>.
 Finally, <tt>(not a)</tt> rules the second occurrence of <tt>c</tt> and <tt>(g c)</tt>.
 </p>

 <p>
 Note that our definition of &ldquo;rulers&rdquo; does not include every test that has to
 be true in order to reach the occurrence in question.  For example, <tt>p</tt>
 does not rule the occurrence of <tt>a</tt> in <tt>(car (if p a b))</tt> even though the
 only way evaluation can reach <tt>a</tt> is if <tt>p</tt> is true.  The
 rulers of the occurrence of <tt>a</tt> in that term is the empty set, because
 that term is not a call of <tt>if</tt>.  However, <tt>p</tt> does rule the
 occurrence of <tt>a</tt> in the equivalent term <tt>(if p (car a) (car b))</tt>.
 The reason we've defined rulers this way has to do with heuristics in the
 ACL2 theorem prover.
 </p>

 <p>
 <b>Principle of Structural Recursion:</b> A definition, <tt>(defun</tt> <i>f</i>&nbsp; <tt>(</tt><i>v_1</i>&nbsp;&hellip;&nbsp;<i>v_n</i><tt>)</tt>&nbsp;<i>&beta;</i><tt>)</tt> will be allowed (for now) only if it satisfies
 these four restrictions:
 </p>

 <ol>
 <li>The symbol being defined, <i>f</i>, must be &ldquo;new,&rdquo; i.e., not already
 in use as a function symbol in any axiom.

 <p/>
 </li>
 <li>The formal variables, <i>v_1</i>,&nbsp;&hellip;&nbsp;, <i>v_n</i>, must be distinct variable
 symbols.

 <p/>
 </li>
 <li>The body, <i>&beta;</i>, must be a term, it must use no new function symbol
 other than (possibly) <i>f</i>, and the only variable symbols in it are among the
 formals.

 <p/>
 </li>
 <li>There is an <i>i</i>&nbsp; such that <tt>(consp</tt> <i>v_i</i><tt>)</tt> rules every recursive
 call of <i>f</i>&nbsp; in <i>&beta;</i>&nbsp; and for every recursive call (<i>f</i>&nbsp; <i>a_1</i>&nbsp;...&nbsp;<i>a_n</i>)
 in <i>&beta;</i>, <i>a_i</i>&nbsp; is a <tt>car</tt>/<tt>cdr</tt> nest around <i>v_i</i>.  We call <i>v_i</i>
 a <i>measured formal</i>.
 </li>
 </ol>

 <p>
 An acceptable definition adds the axiom <tt>(</tt><i>f</i>&nbsp; <i>v_1</i>&nbsp; &nbsp;&hellip;&nbsp; <i>v_n</i><tt>) = </tt><i>&beta;</i>.
 </p>

<p>(Maybe explore &lt;&lt;@(tsee defun)&gt;&gt;?  Be advised, however, that
ACL2's Definitional Principle does not insist on the last condition above,
about there being a <tt>car</tt>/<tt>cdr</tt> nest in a certain argument of every
recursive call.  Instead it insists that &ldquo;some measure of the arguments
decreases&rdquo; in every recursive call.  We'll make that clearer later.  But
ACL2's Definitional Principle allows all the definitions described above.)</p>

 <p>
 <b>Problem 30. <br/></b> Explain why these restrictions rule out the spurious definitions of <tt>f</tt>
 in the problems above.
 </p>

 <p>
 <b>Problem 31. <br/></b> Is the following definition allowed under the above restrictions?
 <code>
 (defun f (x)
   (if (consp x)
       (if (consp (cdr x))
           (f (cdr (cdr x)))
           nil)
       t))
 </code>
 </p>

 <p>
 <b>Problem 32. <br/></b> Is the following definition allowed?
 <code>
 (defun f (x y)
   (if (consp x)
       (f (cons nil x) (cdr y))
       y))
 </code>
 </p>

 <p>
 <b>Problem 33. <br/></b> Is the following definition allowed?
 <code>
 (defun f (x y)
   (if (consp x)
       (f (cons nil y) (cdr x))
       y))
 </code>
 </p>

 <p>
 <b>Problem 34. <br/></b> Is the following definition allowed?
 <code>
 (defun f (x)
   (if (not (consp x))
       x
       (f (cdr (cdr x)))))
 </code>
 </p>

 <p>
 <b>Problem 35. <br/></b> Is the following sequence of definitions allowed?
 <code>
 (defun endp (x) (not (consp x)))

 (defun f (x)
   (if (endp x)
       nil
       (cons nil (f (cdr x)))))
 </code>
 </p>

 <p>
 <b>Problem 36. <br/></b> Is the following definition allowed?
 <code>
 (defun f (x y)
   (if (consp x)
       (f (cdr x) (cons nil y))
       y))
 </code>
 </p>

 <p>
 <b>Problem 37. <br/></b> Is the following definition allowed?
 <code>
 (defun f (x y)
   (if (consp x)
       (f (cdr x)
          (f (cdr x) y))
       y))
 </code>
 </p>

 <p>
 <b>Problem 38. <br/></b> Is the following sequence of definitions allowed?
 <code>
 (defun f (x)
   (if (consp x)
       (g (cdr x))
       x))

 (defun g (x)
   (if (consp x)
       (f (cdr x))
       x))
 </code>
 </p>

 <p>Next: <see topic='@(url r-and-i-structural-induction)'>Structural
 Induction</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-structural-induction
  :parents (recursion-and-induction)
  :short "Recursion and Induction: Structural Induction"
  :long "<p>
 <b>Problem 39. <br/></b> Given the definition
 <code>
 (defun f (x)
   (if (consp x)
       (f (cdr x))
       t))
 </code>
 </p>
 <p>
 can you prove the theorem <tt>(equal (f x) t)</tt> using the logical
 machinery we have described so far?
 </p>

 <p>
 ACL2 supports inductive proofs.  Its Induction Principle is quite general and
 involves the notion of the ordinals and well-foundedness.  We use a much
 simpler principle for now.
 </p>

 <p>
 A substitution <i>&sigma;</i>&nbsp; is a <i><tt>car</tt>/<tt>cdr</tt> substitution</i>&nbsp; on
 <i>v</i>&nbsp; if the binding (image) of <i>v</i>&nbsp; under <i>&sigma;</i>&nbsp; is a
 <tt>car</tt>/<tt>cdr</tt> nest around <i>v</i>.  The other bindings of
 <i>&sigma;</i>&nbsp; are unrestricted.  For example, <i>&sigma;</i>&nbsp; = {<tt>x
   &larr; (car x), y &larr; (cons (cdr x) y)</tt>} is a
 <tt>car</tt>/<tt>cdr</tt> substitution on <tt>x</tt>.
 </p>

 <p>
 <b>Principle of Structural Induction:</b>
 Let <tt><i>&psi;</i></tt> be the term representing a conjecture.
 <tt><i>&psi;</i></tt> may be proved by selecting an &ldquo;induction&rdquo; variable
 <tt>x</tt>, selecting a set of <tt>car</tt>/<tt>cdr</tt> substitutions on
 <tt>x</tt> <i>&sigma;_1</i>,&nbsp;&hellip;&nbsp;, <i>&sigma;_n</i>, and by proving the following
 subgoals:
 </p>

 <p>
 <code>
 <i>Base Case:</i>
 (implies (not (consp x))
          <i>&psi;</i>)</code>
 </p>

 <p>
 and
 </p>

 <p>
 <code>
 <i>Induction Step:</i>
 (implies (and (consp x)   ; <i>test</i>
               <i>&psi;</i>/<i>&sigma;_1</i>&nbsp;  ; <i>induction hypothesis 1</i>
               .
               .
               .
               <i>&psi;</i>/<i>&sigma;_n</i>)  ; <i>induction hypothesis n</i>
          <i>&psi;</i>)  ; <i>induction conclusion</i></code>
 </p>

 <p>
 Here is an example Induction Step.
 <code>
 (implies (and (consp x)
               <i>&psi;</i>/{x &larr; (car x), y &larr; (app x y)}
               <i>&psi;</i>/{x &larr; (cdr (cdr x)), y &larr; (cons x y)}
               <i>&psi;</i>/{x &larr; (cdr (cdr x)), y &larr; y})
          <i>&psi;</i>)</code>
 </p>

 <p>
 Let us use structural induction to prove a theorem about <tt>tree-copy</tt>.
 Recall the definition.
 <code>
 (defun tree-copy (x)
   (if (consp x)
       (cons (tree-copy (car x))
             (tree-copy (cdr x)))
       x))
 </code>
 </p>

 <p>
 <b>Theorem</b> <tt>(equal (tree-copy x) x)</tt>.
 </p>

 <p>
 <b>Proof</b>.
 </p>

 <p>
 Name the formula above *1.
 </p>

 <p>
 We prove *1 by induction.  One induction scheme
 is suggested by this conjecture &ndash; namely the one
 that unwinds the recursion in <tt>tree-copy</tt>.
 </p>

 <p>
 If we let <i>&psi;</i>&nbsp; denote *1 above then the
 induction scheme we'll use is
 <code>
 (and (implies (not (consp x))
               <i>&psi;</i>)
      (implies (and (consp x)
                    <i>&psi;</i>/{x &larr; (car x)}
                    <i>&psi;</i>/{x &larr; (cdr x)})
               <i>&psi;</i>)).</code>
 </p>

 <p>
 When applied to the goal at hand the above induction scheme
 produces the following two nontautological subgoals.
 </p>

 <p>
 <code>
 Subgoal *1/2
 (implies (not (consp x))
          (equal (tree-copy x) x)).</code>
 </p>

 <p>
 But simplification reduces this to <tt>t</tt>, using the definition of
 <tt>tree-copy</tt> and the primitive axioms.
 </p>

 <p>
 <code>
 Subgoal *1/1
 (implies (and (consp x)                             ; <i>hyp 1</i>
               (equal (tree-copy (car x)) (car x))   ; <i>hyp 2</i>
               (equal (tree-copy (cdr x)) (cdr x)))  ; <i>hyp 3</i>
          (equal (tree-copy x) x)).</code>
 </p>

 <p>
 But simplification reduces this to <tt>t</tt>, using the definition of
 <tt>tree-copy</tt> and the primitive axioms.
 </p>

 <p>
 That completes the proof of *1.
 </p>

 <p>
 <b>Q.E.D.</b>


 </p>

 <p>
 Let us look more closely at the reduction of Subgoal *1/1.  Consider the
 left-hand side of the concluding equality.  Here is how it reduces to the
 right-hand side under the hypotheses.
 <code>
 (tree-copy x)
 =                      <i>{def </i><tt>tree-copy</tt><i>}</i>
 (if (consp x)
     (cons (tree-copy (car x))
           (tree-copy (cdr x)))
     x)
 =                      <i>{hyp 1 and Axiom 6}</i>
 (if t
     (cons (tree-copy (car x))
           (tree-copy (cdr x)))
     x)
 =                      <i>{Axioms 2 and 1}</i>
 (cons (tree-copy (car x))
       (tree-copy (cdr x)))
 =                      <i>{hyp 2}</i>
 (cons (car x)
       (tree-copy (cdr x)))
 =                      <i>{hyp 3}</i>
 (cons (car x)
       (cdr x))
 =                      <i>{Axioms 11 and 6 and hyp 1}</i>
 x</code>
 </p>

 <p>
 This proof is of a very routine nature: induct so as to unwind some
 particular function appearing in the conjecture and then use the axioms and
 definitions to simplify each case to <tt>t</tt>.
 </p>

 <p>
 The problems below refer to function symbols defined in previous exercises.
 Try to prove them for the definitions you wrote.  But if you cannot, then use
 the definitions we use in our solutions.  For each conjecture below that is not
 a theorem, show a counterexample and then try to write the theorem
 &ldquo;suggested&rdquo; by the conjecture.  For example, add a hypothesis that
 restricts some variable so that the conjecture holds; you may even need to
 introduce new concepts.
 </p>

 <p><b>Warning:</b> Proving implications by induction is a little tricky.
 Suppose you're trying to prove <tt>(implies (p x) (q x))</tt> by induction and you
 choose the substitution that replaces <tt>x</tt> by <tt>(cdr x)</tt>.  So the
 Induction Step will be</p>

 <code>
 Induction Step.
 (implies (and (consp x)
               (implies (p (cdr x)) (q (cdr x))))
          (implies (p x) (q x))).
 </code>

<p>By propositional calculus, this is the same as</p>

<code>
 (implies (and (consp x)
               (implies (p (cdr x)) (q (cdr x)))
               (p x))
          (q x)).
</code>

<p>Many students act like the induction hypothesis is that <tt>(q (cdr x))</tt>
is true and use that to show <tt>(q x)</tt> is true.  But the induction
hypothesis is actually <tt>(implies (p (cdr x)) (q (cdr x)))</tt>.  It tells us
that <tt>(q (cdr x))</tt> is true <i>if</i> <tt>(p (cdr x))</tt> is true!  So
it often happens that you will use the <tt>(p x)</tt> hypothesis to prove
<tt>(p (cdr x))</tt> is true.  Only then can you use <tt>(q (cdr x))</tt> to
work on <tt>(q x)</tt>.</p>

 <p>
 <b>Problem 40. <br/></b> Prove
 <code>
 (equal (app (app a b) c) (app a (app b c))).
 </code>
 </p>

 <p>
 <b>Problem 41. <br/></b> Prove
 <code>
 (equal (app a nil) a)
 </code>
 </p>

 <p>
 <b>Problem 42. <br/></b> Prove
 <code>
 (equal (mapnil (app a b)) (app (mapnil a) (mapnil b)))
 </code>
 </p>

 <p>
 <b>Problem 43. <br/></b> Prove
 <code>
 (equal (rev (mapnil x)) (mapnil (rev x)))
 </code>
 </p>

 <p>
 <b>Problem 44. <br/></b> Prove
 <code>
 (equal (rev (rev x)) x)
 </code>
 </p>

 <p>
 <b>Problem 45. <br/></b> Prove
 <code>
 (equal (swap-tree (swap-tree x)) x)
 </code>
 </p>

 <p>
 <b>Problem 46. <br/></b> Prove
 <code>
 (equal (mem e (app a b)) (or (mem e a) (mem e b)))
 </code>
 </p>

 <p>
 <b>Problem 47. <br/></b> Prove
 <code>
 (equal (mem e (int a b)) (and (mem e a) (mem e b)))
 </code>
 </p>

 <p>
 <b>Problem 48. <br/></b> Prove
 <code>
 (sub a a)
 </code>
 </p>

 <p>
 <b>Problem 49. <br/></b> Prove
 <code>
 (implies (and (sub a b)
               (sub b c))
          (sub a c))
 </code>
 </p>

 <p>
 <b>Problem 50. <br/></b> Prove
 <code>
 (sub (app a a) a)
 </code>
 </p>

 <p>
 <b>Problem 51. <br/></b> Define
 <code>
 (defun mapnil1 (x a)
    (if (consp x)
        (mapnil1 (cdr x) (cons nil a))
        a))
 </code>
 </p>
 <p>
 Formalize and then prove the remark &ldquo;On lists of <tt>nil</tt>s, <tt>mapnil1</tt>
 is commutative.&rdquo;
 </p>

 <p>
 <b>Problem 52. <br/></b> Define <tt>(perm x y)</tt> so that it returns <tt>t</tt> if lists <tt>x</tt> and
 <tt>y</tt> are permutations of each other; otherwise it returns <tt>nil</tt>.
 </p>

 <p>
 <b>Problem 53. <br/></b> Prove
 <code>
 (perm x x)
 </code>
 </p>

 <p>
 <b>Problem 54. <br/></b> Prove
 <code>
 (implies (perm x y) (perm y x)).
 </code>
 </p>

 <p>
 <b>Problem 55. <br/></b> Prove
 <code>
 (implies (and (perm x y)
               (perm y z))
          (perm x z))
 </code>
 </p>

 <p>
 For several of the problems below it is necessary to have a total ordering
 relation.  Let <tt>&lt;&lt;=</tt> be a non-strict total order, i.e., a Boolean
 function that enjoys the following properties:
 <code>
 (and (&lt;&lt;= x x)                 ; Reflexive
      (implies (and (&lt;&lt;= x y)   ; Anti-symmetric
                    (&lt;&lt;= y x))
               (equal x y))
      (implies (and (&lt;&lt;= x y)   ; Transitive
                    (&lt;&lt;= y z))
               (&lt;&lt;= x z))
      (or (&lt;&lt;= x y)             ; Total
          (&lt;&lt;= y x)))
 </code>
 </p>
 <p>
 Actually, there is such a function in ACL2 and it is called <tt>lexorder</tt>.
 But we use the more suggestive name &ldquo;<tt>&lt;&lt;=</tt>&rdquo; here.  On the integers,
 <tt>&lt;&lt;=</tt> is just <tt>&lt;=</tt>, but it orders all ACL2 objects.
 </p>

 <p>
 <b>Problem 56. <br/></b> Define <tt>(ordered x)</tt> so that it returns <tt>t</tt> or <tt>nil</tt> according to
 whether each pair of adjacent elements of <tt>x</tt> are in the relation
 <tt>&lt;&lt;=</tt>.  For example, <tt>(ordered '(1 3 3 7 12))</tt> would
 evaluate to <tt>t</tt> and
 <tt>(ordered '(1 3 7 3 12))</tt> would evaluate to <tt>nil</tt>.
 </p>

 <p>
 <b>Problem 57. <br/></b> Define <tt>(isort x)</tt> to take an arbitrary list and return an
 <tt>ordered</tt> permutation of it.
 </p>

 <p>
 <b>Problem 58. <br/></b> Prove
 <code>
 (ordered (isort x)).
 </code>
 </p>

 <p>
 <b>Problem 59. <br/></b> Prove
 <code>
 (perm (isort x) x).
 </code>
 </p>

 <p>
 <b>Problem 60. <br/></b> Prove
 <code>
 (equal (isort (rev (isort x)))
        (isort x)).
 </code>
 </p>
 <p>
 We thank Pete Manolios for suggesting this problem.
 </p>

 <p>
 <b>Problem 61. <br/></b> Define
 <code>
 (defun rev1 (x a)
   (if (consp x)
       (rev1 (cdr x) (cons (car x) a))
       a))
 </code>
 </p>
 <p>
 Prove
 <code>
 (equal (rev1 x nil) (rev x))
 </code>
 </p>

 <p>
 <b>Problem 62. <br/></b> Prove
 <code>
 (equal (mapnil1 x nil) (mapnil x))
 </code>
 </p>

 <p>
 <b>Problem 63. <br/></b> Prove
 <code>
 (not (equal x (cons x y)))
 </code>
 </p>

 <p>
 <b>Problem 64. <br/></b> Define
 <code>
 (defun mcflatten (x a)
   (if (consp x)
       (mcflatten (car x)
                  (mcflatten (cdr x) a))
       (cons x a)))
 </code>
 </p>

 <p>Prove</p>

 <p>
 <code>
 (equal (mcflatten x nil) (flatten x))
 </code>
 </p>

 <p>Next: <see topic='@(url r-and-i-arithmetic)'>Arithmetic</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-arithmetic
  :parents (recursion-and-induction)
  :short "Recursion and Induction: Arithmetic"
  :long "<p>We will next discuss arithmetic, in two steps.  First, we'll
  challenge you to use what we have already got to define &ldquo;natural
  numbers&rdquo; (non-negative integers) and the elementary operations on them.  This
  is called &ldquo;Peano&rdquo; arithmetic after the 19th century Italian
  mathematician Giuseppe Peano who first wrote down formal axioms describing
  the natural numbers.</p>

  <p>After you've explored the foundations of arithmetic, we'll talk about
  briefly about the more familiar arithmetic of integers and rationals.</p>

  <p>Next: <see topic='@(url r-and-i-peano-arithmetic)'>Peano
  Arithmetic</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(order-subtopics r-and-i-arithmetic
  (r-and-i-peano-arithmetic r-and-i-acl2-arithmetic))
other
(defxdoc r-and-i-peano-arithmetic
  :parents (r-and-i-arithmetic)
  :short "Recursion and Induction: Peano Arithmetic"
  :long "<p>
 Recall that the integers are being treated as atomic objects in this
 document.  But we can explore elementary arithmetic by thinking of a list of
 <i>n</i>&nbsp; <tt>nil</tt>s as a representation for the natural number <i>n</i>.  We will call
 such a list a &ldquo;nat.&rdquo;  Thus, <tt>(nil nil nil)</tt> is a nat, but <tt>3</tt> is a
 natural number.
 </p>

 <p>
 <b>Problem 65. <br/></b> Define <tt>(nat x)</tt> to recognize nats.
 </p>

 <p>
 <b>Problem 66. <br/></b> Define <tt>(plus x y)</tt> to take two arbitrary lists (even ones that are not
 nats) and to return the nat representing the sum of their lengths.
 By defining <tt>plus</tt> this way we ensure that it always returns a nat
 and that it is commutative.
 </p>

 <p>
 <b>Problem 67. <br/></b> Define <tt>(times x y)</tt> to take two arbitrary lists and to return the
 nat representing the product of their lengths.
 </p>

 <p>
 <b>Problem 68. <br/></b> Define <tt>(power x y)</tt> to take two arbitrary lists and to return the
 nat representing the exponentiation of their lengths, i.e., if <tt>x</tt> and
 <tt>y</tt> are of lengths <i>i</i>&nbsp; and <i>j</i>, then <tt>(power x y)</tt> should return
 the nat representing <i>i^j</i>.
 </p>

 <p>
 <b>Problem 69. <br/></b> Define <tt>(lesseqp x y)</tt> to return <tt>t</tt> or <tt>nil</tt> according to whether
 the length of <tt>x</tt> is less than or equal to that of <tt>y</tt>.
 </p>

 <p>
 <b>Problem 70. <br/></b> Define <tt>(evennat x)</tt> to return <tt>t</tt> or <tt>nil</tt> according to whether
 the length of <tt>x</tt> is even.
 </p>

 <p>
 <b>Problem 71. <br/></b> Prove
 <code>
 (implies (nat i)
          (equal (plus i nil) i))
 </code>
 </p>

 <p>
 <b>Problem 72. <br/></b> Prove
 <code>
 (equal (plus (plus i j) k)
        (plus i (plus j k)))
 </code>
 </p>

 <p>
 <b>Problem 73. <br/></b> Prove
 <code>
 (equal (plus i j) (plus j i))
 </code>
 </p>

 <p>
 <b>Problem 74. <br/></b> Prove
 <code>
 (equal (times (times i j) k)
        (times i (times j k)))
 </code>
 </p>

 <p>
 <b>Problem 75. <br/></b> Prove
 <code>
 (equal (times i j) (times j i))
 </code>
 </p>

 <p>
 <b>Problem 76. <br/></b> Prove
 <code>
 (equal (power b (plus i j))
        (times (power b i) (power b j)))
 </code>
 </p>

 <p>
 <b>Problem 77. <br/></b> Prove
 <code>
 (equal (power (power b i) j)
        (power b (times i j)))
 </code>
 </p>

 <p>
 <b>Problem 78. <br/></b> Prove
 <code>
 (lesseqp i i)
 </code>
 </p>

 <p>
 <b>Problem 79. <br/></b> Prove
 <code>
 (implies (and (lesseqp i j)
               (lesseqp j k))
          (lesseqp i k))
 </code>
 </p>

 <p>
 <b>Problem 80. <br/></b> Prove
 <code>
 (equal (lesseqp (plus i j) (plus i k))
        (lesseqp j k))
 </code>
 </p>

 <p>
 <b>Problem 81. <br/></b> Prove
 <code>
 (implies (and (evennat i)
               (evennat j))
          (evennat (plus i j)))
 </code>
 </p>

 <p>Next: <see topic='@(url r-and-i-acl2-arithmetic)'>ACL2
 Arithmetic</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-acl2-arithmetic
  :parents (r-and-i-arithmetic)
  :short "Recursion and Induction: ACL2 Arithmetic"
  :long "<p>
 The techniques we have studied so far suffice to prove the most elementary
 facts of natural number arithmetic.  In fact, we could conduct our entire
 study of recursion and induction in the domain of number theory.  But it is
 more fun to deal with less familiar &ldquo;data structures&rdquo; where basic
 properties can be discovered.  So we will skip past formal arithmetic with
 a few brief remarks.
 </p>

 <p>
 ACL2 provides the numbers as a data type distinct from conses, symbols,
 strings, and characters.  They are not lists of <tt>nil</tt>s!  The naturals are
 among the integers, the integers are among the rationals, and the rationals
 are among the ACL2 numbers.  The complex rationals are also among the ACL2
 numbers; in fact they are complex numbers whose real and imaginary parts are
 rational and whose imaginary parts are non-<tt>0</tt>.
 </p>

 <p>
 Here are a few commonly used functions in ACL2.
 </p>

 <dl>
 <dt></dt>
 <dd><tt>(natp x)</tt> - recognizes natural numbers

 <p/>
 </dd>
 <dt></dt>
 <dd><tt>(integerp x)</tt> - recognizes integers

 <p/>
 </dd>
 <dt></dt>
 <dd><tt>(rationalp x)</tt> - recognizes rationals

 <p/>
 </dd>
 <dt></dt>
 <dd><tt>(zp x)</tt> - <tt>t</tt> if x is <tt>0</tt> or not a natural; <tt>nil</tt>
       otherwise

 <p/>
 </dd>
 <dt></dt>
 <dd><tt>(nfix x)</tt> - <tt>x</tt> if <tt>x</tt> is a natural; <tt>0</tt> otherwise

 <p/>
 </dd>
 <dt></dt>
 <dd><tt>(+ x y)</tt> - sum of the numbers <tt>x</tt> and <tt>y</tt>

 <p/>
 </dd>
 <dt></dt>
 <dd><tt>(- x y)</tt> - difference of the numbers <tt>x</tt> and <tt>y</tt>

 <p/>
 </dd>
 <dt></dt>
 <dd><tt>(* x y)</tt> - product of the numbers <tt>x</tt> and <tt>y</tt>

 <p/>
 </dd>
 <dt></dt>
 <dd><tt>(/ x y)</tt> - rational quotient of the numbers <tt>x</tt> and <tt>y</tt>

 <p/>
 </dd>
 <dt></dt>
 <dd><tt>(&lt; x y)</tt> - predicate recognizing that the number <tt>x</tt> is less
       than the number <tt>y</tt>

 <p/>
 </dd>
 <dt></dt>
 <dd><tt>(&lt;= x y)</tt> - predicate recognizing that the number <tt>x</tt> is less
       than or equal to the number <tt>y</tt>
 </dd>
 </dl>

 <p>
 The functions <tt>+</tt>, <tt>-</tt>, <tt>*</tt>, <tt>/</tt>, <tt>&lt;</tt>,
 and <tt>&lt;=</tt> default their arguments to <tt>0</tt> in the sense that if
 some argument is not an ACL2 number then <tt>0</tt> is used instead.
 </p>

 <p>
 The predicate <tt>zp</tt> is commonly used in recursive definitions that treat
 an argument as though it were a natural number and count it down to zero.
 </p>

 <p>
 Here is a &ldquo;definition&rdquo; that accesses the <tt>n</tt>th element of a list,
 treating <tt>n</tt> as a natural.  (This definition is unacceptable under our
 current Principle of Structural Recursion because <tt>(consp x)</tt> does not
 rule the recursive call.  We will return to this point momentarily.)
 <code>
 (defun nth (n x)
   (if (zp n)
       (car x)
       (nth (- n 1) (cdr x))))
 </code>
 </p>
 <p>
 Thus, <tt>(nth 2 '(A B C D))</tt> is <tt>C</tt>.  <tt>(Nth 0 '(A B C D))</tt> is
 <tt>A</tt>.  Interestingly, <tt>(nth -1 '(A B C D))</tt> is also <tt>A</tt>, because
 <tt>-1</tt> satisfies <tt>zp</tt>.  Thus, we can use <tt>nth</tt> with any first
 argument.  (In ACL2, <tt>nth</tt> is defined differently, but equivalently.)
 </p>

 <p>
 The numbers are axiomatized with the standard axioms for rational fields.
 See <see topic='@(url r-and-i-annotated-bibliography)'>reference [3]</see>.
 </p>

 <p>
 <b>Henceforth, you may use arithmetic freely in your proofs and assume any
 theorem of ACL2 arithmetic.  That is, you may assume any ACL2 theorem that
 can be written with the function symbols described above and use it in
 routine arithmetic simplification.  But be careful about what you assume!</b></p>

 <p>For example, the following familiar arithmetic facts are not (quite)
 theorems:
 </p>

 <p>
 <code>
 (equal (+ x 0) x)                ; Additive Identity

 (iff (equal (+ x y) (+ x z))     ; Additive Cancellation
      (equal y z))
 </code>

<p>Why aren't the formulas above theorems?</p>

 </p>
 <p>
 In addition, the following strange fact is a theorem:
 <code>
 (not (equal (* x x) 2))
 </code>
 </p>
 <p>
 That is, we can prove that the square root of 2 is not rational
 and hence not in ACL2.
 </p>

 <p>(Maybe explore ACL2 arithmetic?  You won't need ACL2 arithmetic libraries
 to do the problems here.  But that is good because there is probably not an
 area of mathematics that the typical computer science student knows better
 than arithmetic.  Furthermore, you likely know much more about arithmetic than
 ACL2 does when it is first fired up.  Its performance can be improved by
 including &ldquo;certified books&rdquo; of definitions and theorems about
 arithmetic.  The ACL2 Community Books Repository [4] contains thousands of
 books created by the community.  To load a book into an ACL2 session the
 command &lt;&lt;@(tsee include-book)&gt;&gt; is used.  But there are many
 kinds of arithmetic books to choose from depending on what sort of operations
 are involved in your conjectures.  You might explore books on elementary
 &lt;&lt;@(see arithmetic)&gt;&gt; including some number theory books, or books
 on the arithmetic of &lt;&lt;@(see bit-vectors)&gt;&gt; (which deal with
 concepts like shifting or bitwise logical operations on number), or floating
 point books (see &lt;&lt;@(see rtl)&gt;&gt;; these are useful for verifying
 implementations of floating point operations) or a book on the &lt;&lt;@(see
 gl)&gt;&gt; utility (which provides a bit-blaster for finite arithmetic), or
 &lt;&lt;@(see algebra)&gt;&gt; books (e.g., properties of rings and fields),
 to name a few.)</p>

 <p>Next: <see topic='@(url
 r-and-i-inadequacies-of-structural-recursion)'>Inadequacies of Structural
 Recursion</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-inadequacies-of-structural-recursion
  :parents (recursion-and-induction)
  :short "Recursion and Induction: Inadequacies of Structural Recursion"
  :long "<p>
 Recall that to avoid logical contradictions introduced by &ldquo;bad&rdquo;
 definitions, we imposed four restrictions.  The fourth restriction is very
 constraining: we can only recur on a <tt>car</tt>/<tt>cdr</tt> component of some
 argument and must ensure that that argument satisfies <tt>consp</tt> before the
 recursion.
 </p>

 <p>
 The intent of this restriction was to guarantee that the newly defined
 function terminates.  It is beyond the scope of these notes to explain why
 termination is linked to consistency, but the intuitive explanation is that
 if the recursion cannot go on forever then, for every combination of
 constants to which we apply the function, we could compute a value satisfying
 the definitional equation (given enough computational resources).  From this
 observation we can conclude there exists a mathematical function satisfying
 the definitional equation &ndash; namely, the one that maps inputs to the computed
 outputs.  Thus, given a model of the theory before we added the definition, we
 could extend it to a model of the theory with the new definition added.  This
 establishes the consistency of the extended theory.
 (Remark.  In fact,
 our definitions produce <i>conservative extensions</i>, which we will
 briefly discuss below.)
 The problem with the current version of our fourth restriction is that it is
 too syntactic &ndash; it insists, literally, on the use of <tt>consp</tt>, <tt>car</tt>,
 and <tt>cdr</tt>.  In the ACL2 definitional principle, the fourth restriction is
 less syntactic: it requires that we be able to <i>prove</i>&nbsp; that the
 recursion terminates.  That is, when we propose a new definition, a
 conjecture is generated and if this conjecture can be proved as a theorem,
 then we know the function terminates.
 </p>

 <p>
 The basic idea of this conjecture is to establish that some measure of the
 function's arguments decreases in size as the function recurs, and this
 decreasing cannot go on forever.  If the size were, say, a natural number,
 then we would know the decreasing could not go on forever, because the
 arithmetic less-than relation, <tt>&lt;</tt>, is <i>well-founded</i>&nbsp; on the natural
 numbers.  We discuss well-foundedness more in the next section.
 </p>

 <p>
 <b>Problem 82. <br/></b> Define <tt>(cc x)</tt> to return the number of conses in <tt>x</tt>.  The name
 stands for &ldquo;cons count.&rdquo;
 </p>

 <p>
 <b>Problem 83. <br/></b> Prove that <tt>cc</tt> always returns a non-negative <tt>integer</tt>.
 </p>

 <p>
 <b>Problem 84. <br/></b> If we define
 <code>
 (defun atom (x) (not (consp x)))
 (defun first (x) (car x))
 (defun rest (x) (cdr x))
 </code>
 </p>
 <p>
 then the following &ldquo;definition&rdquo; of <tt>tree-copy</tt> is logically equivalent
 to the acceptable version, but it is considered unacceptable by our syntactic
 fourth restriction:
 <code>
 (defun tree-copy (x)
   (if (atom x)
       x
       (cons (tree-copy (first x))
             (tree-copy (rest x)))))
 </code>
 </p>
 <p>
 Write down a conjecture that captures the idea that the argument to
 <tt>tree-copy</tt> is getting smaller (as measured by <tt>cc</tt>)
 as the function recurs.
 </p>

 <p>
 <b>Problem 85. <br/></b> Prove the conjecture above.  Note that since <tt>cc</tt> is a natural
 number, this proof establishes that <tt>tree-copy</tt> terminates on all
 objects.
 </p>

 <p>
 <b>Problem 86. <br/></b> Define <tt>(rm e x)</tt> to return the result of removing the first occurrence
 (if any) of <tt>e</tt> from <tt>x</tt>.
 Thus, <tt>(rm 3 '(1 2 3 4 3 2 1))</tt> is <tt>(1 2 4 3 2 1)</tt>.
 </p>

 <p>
 <b>Problem 87. <br/></b> Show that the following function terminates.
 <code>
 (defun f23 (e x)
   (if (mem e x)
       (f23 e (rm e x))
       23))
 </code>
 </p>
 <p>
 Note that no <tt>car</tt>/<tt>cdr</tt> nest around <tt>x</tt> is equal to the result
 of <tt>(rm 3 '(1 2 3))</tt>.  Thus, <tt>f23</tt> exhibits a kind of recursion
 we have not seen previously &ndash; but we know it terminates.
 </p>

 <p>
 <b>Problem 88. <br/></b> It is obvious that <tt>(f23 e x)</tt> always return <tt>23</tt>.  Can you prove that with
 our current logical machinery?
 </p>

 <p>
 The key to these termination proofs is that the less-than relation is
 well-founded on the natural numbers.  But consider this famous
 function, known as Ackermann's function,
 <code>
 (defun ack (x y)
   (if (zp x)
       1
       (if (zp y)
           (if (equal x 1) 2 (+ x 2))
           (ack (ack (- x 1) y) (- y 1)))))
 </code>
 </p>
 <p>
 Observe that <tt>ack</tt> can generate some very large numbers.
 For example, <tt>(ack 4 3)</tt> is <tt>65536</tt>.
 </p>

 <p>
 <b>Problem 89. <br/></b> <tt>Ack</tt> always terminates.  Why?  Don't feel compelled to give a
 formal proof, just an informal explanation.
 </p>

 <p>
 In the next three sections of this document we will discuss a well-founded
 relation far more powerful than less-than on the natural numbers.  We will
 then connect that well-foundedness machinery to a new version of the
 Definitional Principle, so that we can admit many interesting recursive
 functions, including <tt>ack</tt>.  We will also connect the well-foundedness
 machinery to a new version of the Induction Principle, so that we can prove
 that <tt>(f23 e x)</tt> is <tt>23</tt> &ndash; and far more interesting theorems.
 </p>

 <p>Next: <see topic='@(url r-and-i-ordinals)'>The Ordinals</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-ordinals
  :parents (recursion-and-induction)
  :short "Recursion and Induction: The Ordinals"
  :long "<p>
 The ordinals are an extension of the naturals that captures an essential
 notion of ordering.  They were invented by Georg Cantor in the late nineteen
 century.  While controversial during Cantor's lifetime, ordinals are among
 the richest and deepest mines of mathematics.  We only scratch the surface
 here.
 </p>

 <p>
 Think of each natural number as denoted by a sequence of strokes, i.e.,
 </p>

 <p>
 <code>
   0             0
   1             &mid;
   2             &mid; &mid;
   3             &mid; &mid; &mid;
   4             &mid; &mid; &mid; &mid;
   &nbsp;&hellip;&nbsp;             &nbsp;&hellip;&nbsp;
   &omega;             &mid; &mid; &mid; &mid; &mid; &nbsp;&hellip;&nbsp;
 </code>
 </p>

 <p>
 The limit of that progression is the ordinal <i>&omega;</i>, an infinite sequence of
 strokes.
 </p>

 <p>
 Ordinal addition is just concatenation.  Observe that adding one to the front
 of <i>&omega;</i>&nbsp; produces <i>&omega;</i>&nbsp; again, which gives rise to a standard
 definition of <i>&omega;</i>: the least ordinal such that adding another stroke at
 the beginning does not change the ordinal.
 </p>

 <p>
 We denote by <i>&omega;</i>&nbsp; + <i>&omega;</i>&nbsp; or <i>&omega;</i>&times;2 the &ldquo;doubly infinite&rdquo;
 sequence that we might write as follows.

 <code>
   &omega; &times; 2         &mid; &mid; &mid; &mid; &mid; &nbsp;&hellip;&nbsp; &mid; &mid; &mid; &mid; &mid; &nbsp;&hellip;&nbsp;
 </code>
 </p>

 <p>
 One way to think of <i>&omega;</i>&times;2 is that it is obtained by replacing each
 stroke in 2 (| |) by <i>&omega;</i>.  Thus, one can imagine <i>&omega;</i>&times;3, <i>&omega;</i>&times;4, etc., which
 leads ultimately to the idea of <i>&omega;</i>&times;<i>&omega;</i>, the ordinal obtained by
 replacing each stroke in <i>&omega;</i>&nbsp; by <i>&omega;</i>.  This is also written as <i>&omega;</i>^2.

 <code>
   &omega;^2           &mid; &mid; &mid; &mid; &mid; &nbsp;&hellip;&nbsp; &mid; &mid; &mid; &mid; &mid; &nbsp;&hellip;&nbsp; &mid; &mid; &mid; &mid; &mid; &nbsp;&hellip;&nbsp; &mid; &mid; &mid; &mid; &mid; &nbsp;&hellip;&nbsp; &mid; &mid; &mid; &mid; &mid; &nbsp;&hellip;&nbsp; &nbsp;&hellip;&nbsp;
 </code>
 </p>

 <p>
 We can analogously construct <i>&omega;</i>^3 by replacing each stroke in
 <i>&omega;</i>&nbsp; by <i>&omega;</i>^2 (which, it turns out, is the same as replacing each
 stroke in <i>&omega;</i>^2 by <i>&omega;</i>).  That is, we can construct <i>&omega;</i>^3
 as <i>&omega;</i>&nbsp; copies of <i>&omega;</i>^2, and so on.  This ultimately suggests
 <i>&omega;</i>^<i>&omega;</i>.  We can then stack <i>&omega;</i>s, i.e.,
 <i>&omega;</i>^(<i>&omega;</i>^<i>&omega;</i>), etc.  Consider the limit of all of those stacks,
 </p>

 <p>
 <tt>
 <i>&omega;</i>^(<i>&omega;</i>^(<i>&omega;</i>^(<i>&omega;</i>^(<i>&omega;</i>^(<i>&omega;</i>^(<i>&omega;</i>^&nbsp;&hellip;&nbsp;)))))).
 </tt>
 </p>

 <p>
 That limit is <i>&epsilon;_0</i>.  (As the subscript suggests, there are lots
 more ordinals!  But ACL2 stops with <i>&epsilon;_0</i>.)
 </p>

 <p>
 Despite the plethora of ordinals, we can represent all the ones below
 <i>&epsilon;_0</i>&nbsp; in ACL2, using lists.  Below we begin listing some ordinals up
 to <i>&epsilon;_0</i>; the reader can fill in the gaps at his or her leisure.  We
 show in the left column the conventional notation and in the right column the
 ACL2 object representing the corresponding ordinal.
 </p>

 <table class="PAD " style="">
 <tr><td class="RIGHT">ordinal</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">ACL2 representation</td>
 </tr>
 <tr><td class="RIGHT">&nbsp;</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">&nbsp;</td>
 </tr>
 <tr><td class="RIGHT">0</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">0</td>
 </tr>
 <tr><td class="RIGHT">1</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">1</td>
 </tr>
 <tr><td class="RIGHT">2</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">2</td>
 </tr>
 <tr><td class="RIGHT">3</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">3</td>
 </tr>
 <tr><td class="RIGHT">&nbsp;&hellip;&nbsp;</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">&nbsp;&hellip;&nbsp;</td>
 </tr>
 <tr><td class="RIGHT"><i>&omega;</i></td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">((1 . 1) . 0)</td>
 </tr>
 <tr><td class="RIGHT"><i>&omega;</i>&nbsp; + 1</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">((1 . 1) . 1)</td>
 </tr>
 <tr><td class="RIGHT"><i>&omega;</i>&nbsp; + 2</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">((1 . 1) . 2)</td>
 </tr>
 <tr><td class="RIGHT">&nbsp;&hellip;&nbsp;</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">&nbsp;&hellip;&nbsp;</td>
 </tr>
 <tr><td class="RIGHT"><i>&omega;</i>&times;2</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">((1 . 2) . 0)</td>
 </tr>
 <tr><td class="RIGHT">(<i>&omega;</i>&times;2) + 1</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">((1 . 2) . 1)</td>
 </tr>
 <tr><td class="RIGHT">&nbsp;&hellip;&nbsp;</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">&nbsp;&hellip;&nbsp;</td>
 </tr>
 <tr><td class="RIGHT"><i>&omega;</i>&times;3</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">((1 . 3) . 0)</td>
 </tr>
 <tr><td class="RIGHT">(<i>&omega;</i>&times;3) + 1</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">((1 . 3) . 1)</td>
 </tr>
 <tr><td class="RIGHT">&nbsp;&hellip;&nbsp;</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">&nbsp;&hellip;&nbsp;</td>
 </tr>
 <tr><td class="RIGHT"><i>&omega;</i>^2</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">((2 . 1) . 0)</td>
 </tr>
 <tr><td class="RIGHT">&nbsp;&hellip;&nbsp;</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">&nbsp;&hellip;&nbsp;</td>
 </tr>
 <tr><td class="RIGHT"><i>&omega;</i>^2 + <i>&omega;</i>&times;4 + 3</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">((2 . 1) (1 . 4) . 3)</td>
 </tr>
 <tr><td class="RIGHT">&nbsp;&hellip;&nbsp;</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">&nbsp;&hellip;&nbsp;</td>
 </tr>
 <tr><td class="RIGHT"><i>&omega;</i>^3</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">((3 . 1) . 0)</td>
 </tr>
 <tr><td class="RIGHT">&nbsp;&hellip;&nbsp;</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">&nbsp;&hellip;&nbsp;</td>
 </tr>
 <tr><td class="RIGHT"><i>&omega;</i>^<i>&omega;</i></td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">((((1 . 1) . 0) . 1) . 0)</td>
 </tr>
 <tr><td class="RIGHT">&nbsp;&hellip;&nbsp;</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">&nbsp;&hellip;&nbsp;</td>
 </tr>
 <tr><td class="RIGHT"><i>&omega;</i>^<i>&omega;</i>&nbsp; + <i>&omega;</i>^99 + <i>&omega;</i>&times;4 + 3</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">((((1 . 1) . 0) . 1) (99 . 1) (1 . 4) . 3)</td>
 </tr>
 <tr><td class="RIGHT">&nbsp;&hellip;&nbsp;</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">&nbsp;&hellip;&nbsp;</td>
 </tr>
 <tr><td class="RIGHT"><i>&omega;</i>^(<i>&omega;</i>^2)</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">((((2 . 1) . 0) . 1) . 0)</td>
 </tr>
 <tr><td class="RIGHT">&nbsp;&hellip;&nbsp;</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">&nbsp;&hellip;&nbsp;</td>
 </tr>
 <tr><td class="RIGHT"><i>&omega;</i>^(<i>&omega;</i>^<i>&omega;</i>)</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">((((((1 . 1) . 0) . 1) . 0) . 1) . 0)</td>
 </tr>
 <tr><td class="RIGHT">&nbsp;&hellip;&nbsp;</td>
 <td align="LEFT">&nbsp;</td><td class="LEFT">&nbsp;&hellip;&nbsp;</td>
 </tr>
 </table>

 <p>
 We say an ordinal is &ldquo;finite&rdquo; if it is not a cons and we define
 <tt>(o-finp x)</tt> to recognize finite ordinals.  Of course, if <tt>x</tt> is an
 ordinal and finite, it is a natural number.  But by defining <tt>o-finp</tt>
 this way we ensure that if an ordinal is not finite we can recur into it with
 <tt>cdr</tt>.
 </p>

 <p>
 To manipulate ordinals we define functions that access the first exponent,
 the first coefficient, and the rest of the ordinal:
 <code>
 (defun o-first-expt (x)
   (if (o-finp x) 0 (car (car x))))

 (defun o-first-coeff (x)
   (if (o-finp x) x (cdr (car x))))

 (defun o-rst (x) (cdr x))
 </code>
 </p>
 <p>
 For example, if <tt>x</tt> is the representation of <i>&omega;</i>^e&times;<i>c</i>&nbsp; + <i>r</i>&nbsp;
 then <tt>(o-first-expt x)</tt> is <i>e</i>, <tt>(o-first-coeff x)</tt> is <i>c</i>&nbsp; and
 <tt>(o-rst x)</tt> is <i>r</i>.
 </p>

 <p>
 Here is the definition of <tt>o-p</tt>, the function that recognizes ordinals.
 <code>
 (defun o-p (x)
   (if (o-finp x)
       (natp x)
       (and (consp (car x))
            (o-p (o-first-expt x))
            (not (equal 0 (o-first-expt x)))
            (natp (o-first-coeff x))
            (&lt; 0 (o-first-coeff x))
            (o-p (o-rst x))
            (o&lt; (o-first-expt (o-rst x))
                (o-first-expt x)))))
 </code>
 </p>
 <p>
 (The ACL2 definition is syntactically different but equivalent.)
 </p>

 <p>
 The function <tt>o&lt;</tt> is the &ldquo;less than&rdquo; relation on ordinals.  We show its
 definition below.  But study the definition of <tt>o-p</tt> first.  It says that
 an ordinal is a list of pairs, terminated by a natural number.  Each pair
 <tt>(e . c)</tt> consists of an exponent <tt>e</tt> and a coefficient <tt>c</tt> and
 represents (<i>&omega;</i>^e)&times;<i>c</i>.  The exponents are themselves ordinals
 and the coefficients are non-0 naturals.  Importantly, the exponents are
 listed in strictly descending order.  The list represents the ordinal
 sum of its elements plus the final natural number.  Thus, ordinals can be
 viewed as polynomials.
 </p>

 <p>
 By insisting on the ordering of exponents we can readily compare two
 ordinals, using <tt>o&lt;</tt> below, in much the same way we can compare
 polynomials.
 </p>

 <p>
 <code>
 (defun o&lt; (x y)
   (if (o-finp x)
       (or (not (o-finp y))
           (&lt; x y))
       (if (o-finp y)
           nil
           (if (equal (o-first-expt x)
                      (o-first-expt y))
               (if (equal (o-first-coeff x)
                          (o-first-coeff y))
                   (o&lt; (o-rst x)
                       (o-rst y))
                   (&lt; (o-first-coeff x)
                      (o-first-coeff y)))
               (o&lt; (o-first-expt x)
                   (o-first-expt y))))))
 </code>
 </p>
 <p>
 (The ACL2 definition is syntactically different but equivalent.)
 </p>

 <p>
 <b>Problem 90. <br/></b> Which is smaller, ordinal a or ordinal b?
 </p>

 <ol>
 <li>a = <tt>23</tt>, b = <tt>100</tt>
 </li>
 <li>a = <tt>1000000</tt>, b = <tt>((1 . 1) . 0)</tt>
 </li>
 <li>a = <tt>((2 . 1) . 0)</tt>, b = <tt>((1 . 2) . 0)</tt>
 </li>
 <li>a = <tt>((3 . 5) (1 . 25) . 7)</tt>, b = <tt>((3 . 5) (2 . 1) . 3)</tt>
 </li>
 <li>a = <tt>((((2 . 1) . 0) . 5) . 3)</tt>, b = <tt>((((1 . 1) . 0) . 5) (1 . 25) . 7)</tt>
 </li>
 </ol>

 <p>
 <b>Problem 91. <br/></b> The <tt>o&lt;</tt> operation can be reduced to lexicographic comparison.
 Define <tt>m2</tt> so that it constructs &ldquo;lexicographic ordinals&rdquo;
 from two arbitrary natural numbers.  Specifically, show that
 the following is a theorem:
 <code>
 (implies (and (natp i1)
               (natp j1)
               (natp i2)
               (natp j2))
          (and (o-p (m2 i1 j1))
               (iff (o&lt; (m2 i1 j1)
                        (m2 i2 j2))
                    (if (equal i1 i2)
                        (&lt; j1 j2)
                        (&lt; i1 i2)))))
 </code>
 </p>

 <p>
 The crucial property of <tt>o&lt;</tt> is that it is <i>well-founded on the
 ordinals</i>.  That is, there is no infinite sequence of ordinals, <i>x_i</i>&nbsp; such
 that &nbsp;&hellip;&nbsp; <i>x_3</i>&nbsp; <tt>o&lt;</tt> <i>x_2</i>&nbsp; <tt>o&lt;</tt> <i>x_1</i>&nbsp; <tt>o&lt;</tt> <i>x_0</i>.
 </p>

 <p>
 <b>Problem 92. <br/></b> What is the longest decreasing chain of ordinals starting from the ordinal
 <tt>10</tt>?  What is the longest decreasing chain of ordinals starting
 from the ordinal <tt>((1 . 1) . 0)</tt>?
 </p>

 <p>
 <b>Problem 93. <br/></b> Construct an infinitely descending <tt>o&lt;</tt> chain of objects.  Note that
 by the well-foundedness of <tt>o&lt;</tt> on the ordinals, your chain will not
 consist entirely of ordinals!
 </p>

 <p>
 <b>Problem 94. <br/></b> Prove that <tt>o&lt;</tt> is well-founded on our ordinals, i.e., those
 recognized by <tt>o-p</tt>.
 </p>

 <p>
 Caution: Using the logical machinery we have developed here, it is not
 possible to state that <tt>o&lt;</tt> is well-founded on the ordinals: that
 requires an existential quantifier and infinite sequences.  However,
 it can be done in a traditional set theoretic setting.  That is, the
 theorem that <tt>o&lt;</tt> is well-founded is a &ldquo;meta-theorem&rdquo;, it can be
 proved about our system but it cannot be proved within our system.
 </p>

 <p>
 Our definitional and induction principles are built on the assumption that
 <tt>o&lt;</tt> is well-founded on the ordinals recognized by <tt>o-p</tt>.  Thus, if
 some ordinal measure of the arguments of a recursive function decreases
 according to <tt>o&lt;</tt> in every recursive call, the recursion cannot go on
 forever.
 </p>

 <p> The representation of ordinals described here is a version of Cantor's
 Normal Form.  See <see topic='@(url r-and-i-annotated-bibliography)'>reference
 [5]</see> or the online documentation topics &lt;&lt;@(see ordinals)&gt;&gt;
 and &lt;&lt;@(see o-p)&gt;&gt;, from which some of the examples above have
 been chosen.  </p>

 <p>Next: <see topic='@(url r-and-i-definitional-principle)'>The Definitional
 Principle</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-definitional-principle
  :parents (recursion-and-induction)
  :short "Recursion and Induction: The Definitional Principle"
  :long "<p>
 Below we give a new definitional principle that subsumes the previously
 given Principle of Structural Recursion.
 </p>

 <p>
 The definition
 </p>

 <p>
 <tt>(defun</tt> <i>f</i>&nbsp; <tt>(</tt><i>v_1</i>&nbsp;&hellip;&nbsp;<i>v_n</i><tt>)</tt> <i>&beta;</i><tt>)</tt>
 </p>

 <p>
 is <i>admissible</i>&nbsp; if and only if
 </p>

 <ol>
 <li><i>f</i>&nbsp; is a new function symbol,
 </li>
 <li>the <i>v_i</i>&nbsp; are distinct variable symbols,
 </li>
 <li><i>&beta;</i>&nbsp; is a term that mentions no variable other than
 the <i>v_i</i>&nbsp; and calls no new function symbol other than (possibly) <i>f</i>, and
 </li>
 <li>there is a term <i>m</i>&nbsp; (called the <i>measure</i>) such that the
 following are theorems:

 <p/>

 <ul>
 <li><i>Ordinal Conjecture</i>

 <p/>
 <tt>(o-p</tt> <i>m</i><tt>)</tt>

 <p/>
 </li>
 <li><i>Measure Conjecture(s)</i>&nbsp;
 For each recursive call of <tt>(</tt><i>f a_1</i>&nbsp;&hellip;&nbsp;<i>a_n</i><tt>)</tt> in <i>&beta;</i>&nbsp; and
 the conjunction <i>q</i>&nbsp; of tests ruling it,

 <p/>
 <tt>(implies</tt> <i>q</i>&nbsp; <tt>(o&lt;</tt> <i>m</i>/<i>&sigma;</i>&nbsp; <i>m</i><tt>))</tt>

 <p/>
 where <i>&sigma;</i>&nbsp; is <tt>{</tt><i>v_1</i>&larr;<i>a_1</i>, &nbsp;&hellip;&nbsp;, <i>v_n</i>&larr;<i>a_n</i><tt>}</tt>.
 </li>
 </ul>
 </li>
 </ol>

 <p>If that definition is admissible, then it adds the axiom:</p>

 <p>
 <tt>(</tt><i>f</i>&nbsp;&nbsp;<i>v_1</i>&nbsp;&hellip;&nbsp;<i>v_n</i><tt>)&nbsp;=&nbsp;</tt><i>&beta;</i>.
 </p>

 <p>
 In each of the problems below, admit the proposed definition, i.e.,
 identify the measure and prove the required theorems.
 </p>

 <p>(Maybe explore &lt;&lt;@(tsee defun)&gt;&gt;?  Note in particular how the
 user can explicitly specify the measure and well-founded relation alleged to
 decrease.  When specified, the system will attempt to prove it decreases as
 per the Definitional Principle.  If no measure is specified by the user, the
 system attempts to find an argument whose @(tsee acl2-count) decreases
 according to @(tsee o<).)</p>

 <p>
 <b>Problem 95. <br/></b> <code>
 (defun tree-copy (x)
   (if (atom x)
       x
       (cons (tree-copy (first x))
             (tree-copy (rest x)))))
 </code>
 </p>

 <p>
 <b>Problem 96. <br/></b> <code>
 (defun ack (x y)
   (if (zp x)
       1
       (if (zp y)
           (if (equal x 1) 2 (+ x 2))
           (ack (ack (- x 1) y) (- y 1)))))
 </code>
 </p>

 <p>
 <b>Problem 97. <br/></b> Recursion like that in <tt>ack</tt> allows us to define functions that cannot be
 defined if we are limited to &ldquo;primitive recursion&rdquo; where a given argument
 is decremented in every recursive call.  That is, the new definitional
 principle is strictly more powerful than the old one.  This can be formalized
 and proved within our system (after we extend the principle of induction
 below).  If you are inclined towards metamathematics, feel free to pursue the
 formalization and ACL2 proof of this.  The existence of non-primitive
 recursive functions, dating from 1928, by Wilhelm Ackermann, a student of
 David Hilbert, was one of the important milestones in our understanding of
 the power and limitations of formal mathematics culminating in Goedel's
 results of the early 1930s.
 </p>

 <p>
 <b>Problem 98. <br/></b> <code>
 (defun f1 (i j)
   (if (and (natp i)
            (natp j)
            (&lt; i j))
       (f1 (+ 1 i) j)
       1))
 </code>
 </p>

 <p>
 <b>Problem 99. <br/></b> <code>
 (defun f2 (x)
   (if (equal x nil)
       2
       (and (f2 (car x))
            (f2 (cdr x)))))
 </code>
 </p>

 <p>
 <b>Problem 100. <br/></b> <code>
 (defun f3 (x y)
   (if (and (endp x)
            (endp y))
       3
       (f3 (cdr x) (cdr y))))
 </code>
 </p>

 <p>
 <b>Problem 101. <br/></b> Suppose <tt>p</tt>, <tt>m</tt>, <tt>up</tt>, and <tt>dn</tt> (&ldquo;down&rdquo;) are
 undefined functions.  Suppose however that you know
 this about <tt>p</tt>, <tt>m</tt>, and <tt>dn</tt>:
 </p>

 <p>
 <code>
 <b>Theorem</b> dn-spec
 (and (o-p (m x))
      (implies (p x)
               (o&lt; (m (dn x)) (m x))))</code>
 </p>

 <p>
 Then admit
 <code>
 (defun f4 (x y q)
   (if (p x)
       (if q
           (f4 y (dn x) (not q))
           (f4 y (up x) (not q)))
       4))
 </code>
 </p>
 <p>
 Note that <tt>f4</tt> is swapping its arguments.  Thus, if <tt>q</tt> starts at
 <tt>t</tt>, say, then in successive calls the first argument is <tt>x</tt>,
 <tt>y</tt>, <tt>(dn x)</tt>, <tt>(up y)</tt>, <tt>(dn (dn x))</tt>, <tt>(up (up y))</tt>,
 etc.  I thank Anand Padmanaban for helping me think of
 and solve this problem.
 </p>

 <p>Next: <see topic='@(url r-and-i-induction-principle)'>The Induction
 Principle</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-induction-principle
  :parents (recursion-and-induction)
  :short "Recursion and Induction: The Induction Principle"
  :long "<p>
 The Induction Principle allows one to derive an arbitrary formula, <i>&psi;</i>, from
 </p>

 <ul>
 <li><i>Base Case</i>&nbsp;:
 <tt>(implies (and (not</tt> <i>q_1</i><tt>) &hellip; (not</tt> <i>q_k</i><tt>))</tt> <i>&psi;</i><tt>)</tt>, and

 <p/>
 </li>
 <li><i>Induction Step(s)</i>&nbsp;:  For each 1&le;<i>i</i>&le;<i>k</i>,<br/>

 <tt>(implies (and </tt><i>q_i</i><tt> </tt><i>&psi;</i>/<i>&sigma;_{i,1}</i> &hellip; <i>&psi;</i>/<i>&sigma;_{i,h_i}</i><tt>)</tt><br/>
 <tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt><i>&psi;</i><tt>)</tt>,

 </li>
 </ul>

 <p>
 provided that for terms <i>m</i>, <i>q_1</i>,...<i>q_k</i>, and substitutions
 <i>&sigma;_{i,j}</i>&nbsp; (1&le;<i>i</i>&le;<i>k</i>, 1&le;<i>j</i>&le;<i>h_i</i>), the following are
 theorems:
 </p>

 <ul>
 <li><i>Ordinal Conjecture</i>&nbsp;:
 <tt>(o-p</tt> <i>m</i><tt>)</tt>, and

 <p/>
 </li>
 <li><i>Measure Conjecture(s)</i>&nbsp;:  For each 1&le;<i>i</i>&le;<i>k</i> and 1&le;<i>j</i>&le;<i>h_i</i>,<br/>
 <tt>(implies </tt><i>q_i</i><tt> (o&lt; </tt><i>m</i>/<i>&sigma;_{i,j}</i>&nbsp; <i>m</i><tt>))</tt>.
 </li>
 </ul>

 <p>Next: <see topic='@(url
 r-and-i-relations-between-recursion-and-induction)'>Relations Between
 Recursion and Induction</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-relations-between-recursion-and-induction
  :parents (recursion-and-induction)
  :short "Recursion and Induction: Relations Between Recursion and Induction"
  :long "<p>
 Informally speaking, a recursive definition is &ldquo;ok&rdquo; if there is an ordinal
 measure that decreases in every recursive call.  Thus, the recursion cannot
 go on forever.  In a simple recursion on naturals down to 0 by -1, the value
 of the function on 5 is determined recursively by its value on 4, which is
 determined recursively by its value on 3, which is determined recursively by
 its value on 2, which is determined recursively by its value on 1, which is
 determined recursively by its value on 0, which is specified explicitly in
 the definition.
 </p>

 <p>
 An inductive proof is &ldquo;ok&rdquo; if there is an ordinal measure that decreases in
 every induction hypothesis.  Thus, any concrete instance of the conjecture
 could be proved by &ldquo;pumping&rdquo; forward a finite number of times from the base
 cases.  Given a simple inductive proof over the naturals, the conjecture is
 true on 0 because it was proved explicitly in the base case, so it is true
 on 1 by the induction step, so it is true on 2 by the induction step, so it
 is true on 3 by the induction step, so it is true on 4 by the induction step,
 so it is true on 5 by the induction step.
 </p>

 <p>
 Clearly these two concepts are duals.  The formal statements of the two
 principles look more different than they are.  They both require us to prove
 that a measure returns an ordinal and that some substitutions make the
 measure decrease under some tests.  But there seems to be a lot less indexing
 going on in the Definitional Principle than in the Induction Principle.  That
 is due to language and the two different uses of the principles.  The
 Definitional Principle is designed to tell us whether a definitional equation
 is ok.  The Induction Principle is designed to tell us whether a set of
 formulas is an ok inductive argument.  So the Definitional Principle talks
 about the tests in <tt>IF</tt>s and the substitution built from each recursive
 call, whereas the Induction Principle talks about the tests in the <i>i</i>th
 formula and the substitution that created the <i>j</i>th induction hypothesis
 of the <i>i</i>th formula.
 </p>

 <p>
 But the key insight is: <i>Every ok definition suggests an ok induction</i>!
 We call this the induction <i>suggested by</i>&nbsp; the definition.  It is easiest
 to see this by considering a particular, generic definition and thinking
 about what had to be proved to admit it, what induction it suggests,
 what has to be proved for that induction to be legal, and when the suggested
 induction might be useful.
 </p>

 <p>
 Suppose the following definition has been admitted, justified by measure term
 <tt>(m x a)</tt>.  Note that the body is an <tt>IF</tt>-tree, and there are three tips in
 the <tt>IF</tt>-tree; the first tip contains two recursive calls, the second tip
 contains one recursive call, and the third tip contains no recursive calls.
 <code>
 (defun f (x a)
   (if (test1 x a)
       (if (test2 x a)
           (h                         ; tip 1
            (f (d1 x a) (a1 x a))     ;   rec call 1,1
            (f (d2 x a) (a2 x a)))    ;   rec call 1,2
           (g                         ; tip 2
            (f (d3 x a) (a3 x a))))   ;   rec call 2,1
       (b x a)))                      ; tip 3</code>
 </p>

 <p>
 To admit this definition we had to prove:
 <code>
 <i>Ordinal Conjecture</i>
 (o-p (m x a))

 <i>Measure Conjecture 1,1</i>
 (implies (and (test1 x a) (test2 x a))
          (o&lt; (m (d1 x a) (a1 x a))
              (m x a)))

 <i>Measure Conjecture 1,2</i>
 (implies (and (test1 x a) (test2 x a))
          (o&lt; (m (d2 x a) (a2 x a))
              (m x a)))

 <i>Measure Conjecture 2,1</i>
 (implies (and (test1 x a) (not (test2 x a)))
          (o&lt; (m (d3 x a) (a3 x a))
              (m x a)))</code>
 </p>

 <p>
 Suppose we want to prove <tt>(p x a)</tt>, by induction according to
 the scheme &ldquo;suggested&rdquo; by <tt>(f x a)</tt>.  Here is the scheme:
 </p>

 <p>
 <code>
 <i>Base Case</i>&nbsp;                              ; for tip 3
 (implies (not (test1 x a))
          (p x a))

 <i>Induction Step 1</i>&nbsp;                       ; for tip 1
 (implies (and (test1 x a)
               (test2 x a)
               (p (d1 x a) (a1 x a))    ;   for rec call 1,1
               (p (d2 x a) (a2 x a)))   ;   for rec call 1,2
          (p x a))

 <i>Induction Step 2</i>&nbsp;                       ; for tip 2
 (implies (and (test1 x a)
               (not (test2 x a))
               (p (d3 x a) (a3 x a)))   ;   for rec call 2,1
          (p x a))</code>
 </p>

 <p>
 This induction is produced by the following parameter choices in the
 Induction Principle:
 </p>

 <p>
 <table class="PAD " style="">
 <tr><td class="LEFT"><i>&psi;</i></td>
 <td class="LEFT"><tt>(p x a)</tt></td>
 </tr>
 <tr><td class="LEFT"><i>m</i></td>
 <td class="LEFT"><tt>(m x a)</tt></td>
 </tr>
 <tr><td class="LEFT"><i>q_1</i></td>
 <td class="LEFT"><tt>(and (test1 x a) (test2 x a))</tt></td>
 </tr>
 <tr><td class="LEFT"><i>q_2</i></td>
 <td class="LEFT"><tt>(and (test1 x a) (not (test2 x a)))</tt></td>
 </tr>
 <tr><td class="LEFT"><i>&sigma;_{1,1}</i></td>
 <td class="LEFT"><tt>{x &larr; (d1 x a), a &larr; (a1 x a)}</tt></td>
 </tr>
 <tr><td class="LEFT"><i>&sigma;_{1,2}</i></td>
 <td class="LEFT"><tt>{x &larr; (d2 x a), a &larr; (a2 x a)}</tt></td>
 </tr>
 <tr><td class="LEFT"><i>&sigma;_{2,1}</i></td>
 <td class="LEFT"><tt>{x &larr; (d3 x a), a &larr; (a3 x a)}</tt></td>
 </tr>
 </table>
 </p>

 <p>
 It should be obvious to you how these choices are determined from the
 definition of <tt>f</tt> with measure <tt>(m x a)</tt>.  For example, <i>q_1</i>&nbsp; is
 the conjunction of the tests leading to the first tip containing recursive
 calls of <tt>f</tt>, and the substitutions <i>&sigma;_{1,j}</i>&nbsp; are the
 substitutions derived from the recursive calls in that tip.
 </p>

 <p>
 The measure conjectures required by the Induction Principle for this
 choice of parameters are exactly
 the same as the measure conjectures verified when the Definitional Principle
 was used to admit <tt>f</tt>!
 That is, to use an induction suggested by an
 already-admitted recursive function, no additional measure conjectures have to be proved.
 </p>

 <p>(Remark on ``exactly the same'' above.  We have propositionally simplified
 the defining condition for the Base Case.  The Induction Principle says it is
 <tt>(and (not <i>q_1</i>) (not <i>q_2</i>))</tt> and the literal instantiation
 of that here would be <tt>(and (not (and (test1 x a) (test2 x a))) (not (and
 (test1 x a) (not (test2 x a)))))</tt>, but that is propositionally equivalent
 to <tt>(not (test1 x a))</tt>.)</p>

 <p>
 But why might this induction be interesting or useful for proving <tt>(p x
     a)</tt>?  The answer depends on <tt>(p x a)</tt>, of course.  But the most
 common situation is that we choose the induction scheme suggested by some
 recursive function used in the conjecture to be proved.  So suppose <tt>(f
     x a)</tt> occurs in <tt>(p x a)</tt>.  Why is the suggested induction likely
 to be helpful?  Consider the Base Case and the two Induction Steps.
 </p>

 <p>
 In the Base Case, the <tt>(f x a)</tt> occurring in <tt>(p x a)</tt> can be
 replaced by tip 3 of the definition of <tt>f</tt>, <tt>(b x a)</tt> because the
 test in the Base Case of the induction is the test leading to the
 non-recursive exit from the definition.  So <tt>f</tt> has been eliminated
 from the proof of the Base Case.
 </p>

 <p>
 Now consider Induction Step 1.  The <tt>(f x a)</tt> occurring in <tt>(p x a)</tt>
 can be replaced by tip 1 of the definition of <tt>f</tt>, namely
 <code>
           (h                         ; tip 1
            (f (d1 x a) (a1 x a))     ;   rec call 1,1
            (f (d2 x a) (a2 x a)))    ;   rec call 1,2</code>
 </p>

 <p>
 because the tests in Induction Step 1 are the tests leading to tip 1 of the definition.
 But notice that the induction hypothesis labeled &ldquo;for rec call 1,1&rdquo; in
 Induction Step 1 gives us a hypothesis about recursive call 1,1 &mdash; because
 the occurrence of <tt>(f x a)</tt> in <tt>(p x a)</tt> becomes an occurrence of
 <tt>(f (d1 x a) (a1 x a))</tt> when we apply the substitution <i>&sigma;_{1,1}</i>
 to it.  Similarly, the induction hypothesis labeled &ldquo;for rec call 1,2&rdquo;
 gives us a hypothesis about call 1,2.  Thus, the proof of Induction Step 1
 boils down to proving, &ldquo;if the two recursive calls in this tip have the
 property we're proving, then <tt>h</tt> of those two calls has the
 property.&rdquo;  While not exactly eliminating <tt>f</tt> from the proof, it
 provides us with all the information that we have a right to suppose about
 <tt>f</tt> in this case.  Usually the proof of this step requires a lemma
 about <tt>p</tt> and <tt>h</tt>, e.g., &ldquo;if <tt>a</tt> and <tt>b</tt> have
 property <tt>p</tt>, then so does <tt>(h a b)</tt>.&rdquo;  Such a lemma would
 eliminate <tt>f</tt>, and if we had that lemma the proof of Induction Step 1
 would be done.  The proof of Induction Step 2 is analogous.
 </p>

 <p>
 Thus, we see that there may well be some heuristic value in using the
 induction suggested by <tt>(f x a)</tt> whenever you are trying to prove a
 property of <tt>(f x a)</tt>.  Occasionally it is necessary to use an
 induction suggested by a function not appearing in the conjecture, but when
 that occurs it is usually some easily recognized &ldquo;mash up&rdquo; of other
 functions appearing in the conjecture.
 </p>

 <p>
 <b>Problem 102. <br/></b> Recall the previously admitted
 <code>
 (defun f1 (i j)
   (if (and (natp i)
            (natp j)
            (&lt; i j))
       (f1 (+ 1 i) j)
       1))
 </code>
 </p>
 <p>
 Prove <tt>(equal (f1 i j) 1)</tt>.
 </p>

 <p>
 <b>Problem 103. <br/></b> Recall the previously admitted
 <code>
 (defun f2 (x)
   (if (equal x nil)
       2
       (and (f2 (car x))
            (f2 (cdr x)))))
 </code>
 </p>
 <p>
 Prove <tt>(equal (f2 x) 2)</tt>.
 </p>

 <p>
 <b>Problem 104. <br/></b> Recall the previously admitted
 <code>
 (defun f3 (x y)
   (if (and (endp x)
            (endp y))
       3
       (f3 (cdr x) (cdr y))))
 </code>
 </p>
 <p>
 Prove <tt>(equal (f3 x y) 3)</tt>.
 </p>

 <p>
 <b>Problem 105. <br/></b> Recall the previously admitted
 <code>
 (defun f4 (x y q)
   (if (p x)
       (if q
           (f4 y (dn x) (not q))
           (f4 y (up x) (not q)))
       4))
 </code>
 </p>
 <p>
 Prove <tt>(equal (f4 x y q) 4)</tt>.
 </p>

 <p>
 These simple inductive exercises drive home the point that once a function
 has been admitted (proved to terminate) then we can do inductions to
 &ldquo;unwind&rdquo; it.  Students so frequently see induction limited to &ldquo;<i>p(n)</i>&nbsp;
 implies <i>p(n+1)</i>&nbsp;&rdquo; that it is easy to forget that every total recursive
 function gives rise to an induction that is appropriate for it.
 </p>

 <p>Next: <see topic='@(url r-and-i-more-problems)'>More Problems</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-more-problems
  :parents (recursion-and-induction)
  :short "Recursion and Induction: More Problems"
  :long "<p>
 <b>Problem 106. <br/></b> Here is a way to flatten a binary tree without using
 an auxiliary function.  Admit this definition.
 <code>
 (defun flatten! (x)
   (if (atom x)
       (cons x nil)
       (if (atom (car x))
           (cons (car x) (flatten! (cdr x)))
           (flatten! (cons (caar x) (cons (cdar x) (cdr x)))))))
 </code>
 </p>

 <p>
 <b>Problem 107. <br/></b> Prove <tt>(equal (flatten! x) (flatten x))</tt>.
 </p>

 <p>
 <b>Problem 108. <br/></b> Here is a clever way to determine if two binary trees have the
 same fringe.  Admit this function (and its subroutine).
 <code>
 (defun samefringe (x y)
  (if (or (atom x)
          (atom y))
      (equal x y)
      (and (equal (car (gopher x))
                  (car (gopher y)))
           (samefringe (cdr (gopher x))
                       (cdr (gopher y))))))
 </code>
 </p>
 <p>
 where
 <code>
 (defun gopher (x)
   (if (or (atom x)
           (atom (car x)))
       x
       (gopher (cons (caar x) (cons (cdar x) (cdr x))))))
 </code>
 </p>

 <p>
 <b>Problem 109. <br/></b> Prove
 <code>
 (equal (samefringe x y)
        (equal (flatten x)
               (flatten y)))
 </code>
 </p>

 <p>
 <b>Problem 110. <br/></b> The curious recursions in <tt>gopher</tt> and <tt>samefringe</tt> are due to John
 McCarthy, who viewed <tt>gopher</tt> as a model of a co-routine.  Explain what
 he was thinking.
 </p>

 <p>
 <b>Problem 111. <br/></b> Below is a model of the functional behavior of QuickSort.  Note
 that <tt>rel</tt> is defined as a &ldquo;higher order&rdquo; function that can
 apply any of four relations.
 <code>
 (defun rel (fn x y)
   (if (equal fn '&lt;&lt;=)
       (&lt;&lt;= x y)
       (if (equal fn '&gt;&gt;=)
           (&lt;&lt;= y x)
           (if (equal fn '&lt;&lt;)
               (and (&lt;&lt;= x y) (not (equal x y)))
               (and (&lt;&lt;= y x) (not (equal x y)))))))

 (defun filter (fn x e)
   (if (endp x)
       nil
       (if (rel fn (car x) e)
           (cons (car x) (filter fn (cdr x) e))
           (filter fn (cdr x) e))))

 (defun qsort (x)
   (if (endp x)
       nil
       (if (endp (cdr x))
           x
           (app (qsort (filter '&lt;&lt; (cdr x) (car x)))
                (cons (car x)
                      (qsort (filter '&gt;&gt;= (cdr x) (car x))))))))
 </code>
 </p>
 <p>
 Prove that <tt>qsort</tt> produces an ordered permutation of its
 input.
 </p>

 <p>
 <b>Problem 112. <br/></b> Prove that the length of a list of distinct natural numbers
 is no greater than its maximum element plus one.  This is sometimes
 called the Pigeon Hole Principle.
 </p>

 <p>
 <b>Problem 113. <br/></b> Imagine a simple list being treated as a &ldquo;memory.&rdquo;  If <i>a</i>&nbsp; is a natural
 number less than the length of the memory, then <i>a</i>&nbsp; is an &ldquo;address&rdquo; and we
 can use <tt>nth</tt> to fetch the contents.  This is &ldquo;dereferencing&rdquo; <i>a</i>.  If
 <i>a</i>&nbsp; is not an address, we will say it is &ldquo;data.&rdquo;  Now consider the idea of
 taking an object and a memory and dereferencing until we get to data.  The
 following function counts the steps; it returns the symbol <tt>infinite</tt> if a
 loop is detected.
 <code>
 (defun deref-cnt (ptr mem seen)
   (if (addressp ptr mem)
       (if (mem ptr seen)
           'infinite
           (inc (deref-cnt (nth ptr mem) mem (cons ptr seen))))
       0))
 </code>
 </p>
 <p>
 where
 <code>
 (defun len (x)
   (if (consp x)
       (+ 1 (len (cdr x)))
       0))

 (defun inc (x)
   (if (integerp x) (+ 1 x) 'infinite))

 (defun addressp (ptr m)
   (and (natp ptr)
        (&lt; ptr (len m))))
 </code>
 </p>
 <p>
 Admit <tt>deref-cnt</tt>.
 </p>

 <p>
 <b>Problem 114. <br/></b> This is a fact every undergraduate knows.  The number of times you can
 dereference (without being in a loop) is bounded by the size of the memory
 (plus one for the initial probe).  Prove it.
 <code>
 (&lt;= (deref-cnt ptr mem nil)
     (+ 1 (len mem)))
 </code>
 </p>
 <p>
 Since <tt>deref-cnt</tt> returns the non-number <tt>infinite</tt> if it
 is a loop, and since ACL2 arithmetic treats non-numbers as <tt>0</tt>,
 this theorem is trivial when the process loops.  You may therefore
 explicitly add the hypothesis <tt>(integerp (deref-cnt ptr mem nil))</tt>
 if you are uncomfortable dealing with the non-numeric defaults.
 </p>

 <p>
 <b>Problem 115. <br/></b> Here is the familiar definition of the Fibonacci function
 and a more efficient one (&ldquo;fast Fibonacci&rdquo;).
 <code>
 (defun fib (i)
   (if (zp i)
       0
       (if (equal i 1)
           1
           (+ (fib (- i 1))
              (fib (- i 2))))))

 (defun ffib (i j k)
   (if (zp i)
       j
       (if (equal i 1)
           k
           (ffib (- i 1) k (+ j k)))))
 </code>
 </p>
 <p>
 Prove they are equal in the following sense
 <code>
 (equal (ffib n 0 1) (fib n))
 </code>
 </p>

 <p>
 <b>Problem 116. <br/></b> Prove
 <code>
 (equal (rotn (len x) x) x)
 </code>
 </p>
 <p>
 where
 <code>
 (defun rot (x)
   (if (endp x)
       nil
       (app (cdr x) (cons (car x) nil))))

 (defun rotn (n x)
   (if (zp n)
       x
       (rotn (- n 1) (rot x))))
 </code>
 </p>

 <p>
 <b>Problem 117. <br/></b> In this problem we explore binary arithmetic.  Let a <i>bit vector</i>&nbsp; be a
 list of Booleans; it is convenient to suppose that the least significant bit
 is the car.  A bit vector represents a natural number in the usual binary
 encoding.  Define <tt>(vadd x y)</tt> to return a bit vector representing the
 sum of the numbers represented by the bit vectors <tt>x</tt> and <tt>y</tt>.
 Formally specify and prove that <tt>vadd</tt> is correct.
 Obviously, this problem can be expanded to include other binary arithmetic
 operations and implementations.
 </p>

 <p>Next: <see topic='@(url
 r-and-i-more-inadequacies-of-the-definitional-principle)'>More Inadequacies of
 the Definitional Principle</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-more-inadequacies-of-the-definitional-principle
  :parents (recursion-and-induction)
  :short "Recursion and Induction: More Inadequacies of the Definitional Principle"
  :long "<p>Next: <see topic='@(url
  r-and-i-mutual-recursion-inadequacies)'>Mutual Recursion
  Inadequacies</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(order-subtopics r-and-i-more-inadequacies-of-the-definitional-principle
  (r-and-i-mutual-recursion-inadequacies r-and-i-problematic-nested-recursion))
other
(defxdoc r-and-i-mutual-recursion-inadequacies
  :parents (r-and-i-more-inadequacies-of-the-definitional-principle)
  :short "Recursion and Induction: Mutual Recursion Inadequacies"
  :long "<p>
 <b>Problem 118. <br/></b> Mutual recursion is (still) not allowed by our statement of the Definitional
 Principle.  However, suppose that somehow the axioms produced by
 the following pair of definitions were available.
 <code>
 (defun fx (x)
   (if (consp x)
       (cons (fx (car x))
             (gx (cdr x)))
       x))

 (defun gx (x)
   (if (consp x)
       (cons (gx (car x))
             (fx (cdr x)))
       x))
 </code>
 </p>
 <p>
 Prove
 <code>
 (equal (fx x) x)
 </code>
 </p>

 <p>
 <b>Problem 119. <br/></b> Develop a methodology for dealing with mutual recursion.
 That is, explain how you can use our Definitional Principle
 to introduce two functions <tt>fx</tt> and <tt>gx</tt> that can
 be shown to satisfy the &ldquo;defining equations&rdquo; for <tt>fx</tt>
 and <tt>gx</tt> above.  Your methodology should work for any
 clique of mutually recursive functions that can be shown to
 terminate under the <tt>o&lt;</tt> relation.
 </p>

 <p>
 <b>Problem 120. <br/></b> We say <tt>x</tt> is an <i>expression</i>&nbsp; if (a) <tt>x</tt> is a symbol or (b)
 <tt>x</tt> is a list of the form <tt>(</tt><i>f</i>&nbsp; <i>e_1</i>&nbsp; &nbsp;&hellip;&nbsp; <i>e_n</i><tt>)</tt>, where <i>f</i>&nbsp; is a symbol
 and the <i>e_i</i>&nbsp; are expressions.  Define <tt>(expr x)</tt> to recognize
 expressions.
 </p>

 <p>
 <b>Problem 121. <br/></b> An <i>expression substitution</i>&nbsp; is a list of 2-tuples of the form
 <tt>(</tt><i>v</i>&nbsp; <i>expr</i><tt>)</tt>, where <i>v</i>&nbsp; is a symbol and <i>expr</i>&nbsp; is an expression.
 Define <tt>substitution</tt> to recognize expression substitutions.
 </p>

 <p>
 <b>Problem 122. <br/></b> Define <tt>(slash x s)</tt> so that it substitutes
 the expression substitution
 <tt>s</tt> into the expression <tt>x</tt>, e.g., it returns <tt>x</tt>/<tt>s</tt>.
 </p>

 <p>
 <b>Problem 123. <br/></b> Prove that if <tt>s</tt> is an expression substitution and <tt>x</tt> is an
 expression, then <tt>(slash x s)</tt> is an expression.
 </p>

 <p>(Maybe explore &lt;&lt;@(see mutual-recursion)&gt;&gt;?)</p>

 <p>Next: <see topic='@(url r-and-i-problematic-nested-recursion)'>Problematic
 Nested Recursion</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-problematic-nested-recursion
  :parents (r-and-i-more-inadequacies-of-the-definitional-principle)
  :short "Recursion and Induction: Problematic Nested Recursion"
  :long "<p>
 <b>Problem 124. <br/></b> The following function cannot be admitted.  Explain why.
 <code>
 (defun f5 (x)
   (if (zp x)
       0
       (+ 1 (f5 (f5 (- x 1))))))
 </code>
 </p>

 <p>
 When the function being defined, <i>f</i>, is called recursively on the value of a
 nested recursive call, e.g., <tt>(</tt><i>f</i>&nbsp; &nbsp;&hellip;&nbsp; (<i>f</i>&nbsp; &nbsp;&hellip;&nbsp;<tt>))</tt>, we say the
 definition exhibits <i>nested recursion</i>.  We have already seen
 some examples of nested recursion:
 </p>

 <p>
 <code>
 (defun mcflatten (x a)
   (if (consp x)
       (mcflatten (car x)
                  (mcflatten (cdr x) a))
       (cons x a)))

 (defun ack (x y)
   (if (zp x)
       1
       (if (zp y)
           (if (equal x 1) 2 (+ x 2))
           (ack (ack (- x 1) y) (- y 1)))))
 </code>
 </p>

 <p>
 <b>Problem 125. <br/></b> What makes the recursion in <tt>f5</tt>, which cannot be admitted,
 different from that in <tt>mcflatten</tt> and <tt>ack</tt>, which can
 be admitted?
 </p>

 <p>
 It is often possible to deal with problematic nested recursion, by admitting
 a different but related definition and then proving that it is equivalent to
 the one you wanted.  The next few problems illustrate this.
 </p>

 <p>
 <b>Problem 126. <br/></b> Admit the following
 <code>
 (defun f5 (x)
   (if (zp x)
       0
       (if (&lt; (nfix (f5 (- x 1))) (nfix x))
           (+ 1 (f5 (f5 (- x 1))))
           'undef)))
 </code>
 </p>

 <p>
 <b>Problem 127. <br/></b> Prove
 <code>
 (implies (natp x) (&lt;= (f5 x) x))
 </code>
 </p>

 <p>
 <b>Problem 128. <br/></b> Prove
 <code>
 (equal (f5 x)
        (if (zp x)
            0
            (+ 1 (f5 (f5 (- x 1))))))
 </code>
 </p>

 <p>
 You may think that problematic nested recursion never arises in actual formal
 models.  Think again!  Consider a graph reachability algorithm, as might be
 implemented in the mark phase of a garbage collector.  Suppose a memory
 location can hold a pair of addresses, a single address, or data.  Given an
 initial address, mark all the reachable addresses, avoiding any possible
 cycles in the data.  When the mark algorithm arrives at an address, <i>ptr</i>,
 containing a pair, it marks that address, explores and marks one of the
 addresses, and then explores and marks the other.  The algorithm terminates
 because marking increases the number of marked addresses in memory and the
 number of addresses is bounded.  But note that when the algorithm explores
 and marks the second address it does so on the memory produced by exploring
 and marking the first address and the parent.  This is problematic nested
 recursion: if the inner recursion <i>unmarked</i>&nbsp; some of the marked
 addresses, the outer sweep might get caught in a cycle.  But we cannot prove
 that the algorithm does not unmark things until we have admitted the model!
 </p>

 <p>
 <b>Problem 129. <br/></b> Let <tt>m</tt> be a list representing a RAM, with 0-based addressing modeled
 by <tt>nth</tt>.  An address is legal if it is a natural less than the length of
 the memory.  If an address contains a pair, we explore both the <tt>car</tt> and
 the <tt>cdr</tt>.  If an address contains an address, we explore that address.
 Cycles may be present.
 The function below collects the list of all addresses reachable from a
 given one.  This definition exhibits problematic nested recursion.
 <code>
 (defun reachables (ptr m seen)
   (if (addressp ptr m)
       (if (mem ptr seen)
           seen
           (if (consp (nth ptr m))
               (reachables (car (nth ptr m))
                           m
                           (reachables (cdr (nth ptr m))
                                       m
                                       (cons ptr seen)))
               (reachables (nth ptr m) m (cons ptr seen))))
       seen))
 </code>
 </p>
 <p>
 Use the method suggested by the <tt>f5</tt> problems to define a function
 satisfying the equation above.
 </p>

 <p>
 <b>Problem 130. <br/></b> Consider the problem of reversing a list.  Our standard definition,
 <tt>rev</tt>, uses an auxiliary function, <tt>app</tt>.  The tail-recursive
 version, <tt>rev1</tt>, uses an additional formal parameter.  Below is a
 definition of reverse that has only one parameter and no auxiliary functions.
 This definition was proposed by Rod M. Burstall in the early 1970s as an
 entertaining puzzle.  It exhibits problematic nested recursion.
 <code>
 (defun rmb (x)
   (if (consp x)
       (if (consp (cdr x))
           (cons (car (rmb (cdr x)))
                 (rmb (cons (car x)
                            (rmb (cdr (rmb (cdr x)))))))
           (cons (car x) nil))
       nil))
 </code>
 </p>
 <p>
 Show how this definition can be derived from an admissible one.
 </p>

 <p>
 <b>Problem 131. <br/></b> Suppose <tt>rmb</tt> is known to satisfy the &ldquo;defining equation&rdquo;
 that would be added by the <tt>defun</tt> above had it been admissible.
 That is, suppose that is the only equation known for <tt>rmb</tt>.
 Prove
 <code>
 (equal (rmb x) (rev x))
 </code>
 </p>

 <p>Next: <see topic='@(url r-and-i-still-more-problems)'>Still More
 Problems</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-still-more-problems
  :parents (recursion-and-induction)
  :short "Recursion and Induction: Still More Problems"
  :long "<p>
 The next several problems will lead you to define a tautology checker
 in ACL2 and to prove that it is sound and complete.  This is an
 excellent exercise if you are interested in theorem proving.
 </p>

 <p>
 <b>Problem 132. <br/></b> An <i><tt>IF</tt>-expression</i>&nbsp; is a cons whose car is <tt>IF</tt>.  A <i>quote</i>&nbsp; is a
 cons whose car is <tt>QUOTE</tt>.  A <i>variable</i>&nbsp; is anything besides an
 <tt>IF</tt>-expression or a quote.  An <i>expression</i>&nbsp; is a variable,
 a quote, or an <tt>IF</tt>-expression.
 </p>

 <p>
 Note: By these definitions, any object is an expression.  But we typically
 think of <tt>IF</tt>-expressions as being of the form <tt>(IF</tt> <i>a_1</i> <i>a_2</i>
 <i>a_3</i><tt>)</tt> and quotes being of the form <tt>(QUOTE</tt> <i>a</i><tt>)</tt>.  But rather than
 check that they are of this form we will just use <tt>car</tt> and <tt>cdr</tt> to
 chew into <tt>IF</tt>s and quotes to access the desired substructure, which we
 will call &ldquo;arguments&rdquo; one, two, and three.
 </p>

 <p>
 An <i>assignment</i>&nbsp; is a list of pairs, <tt>(</tt><i>var</i><tt> . </tt><i>val</i><tt>)</tt>, where <i>var</i>&nbsp;
 is a variable and <i>val</i>&nbsp; is an arbitrary object (but is typically a Boolean).
 </p>

 <p>
 We define the <i>value</i>&nbsp; of an expression under an assignment as follows.
 The <i>value</i>&nbsp; of a variable is the <i>val</i>&nbsp; associated with that variable, or
 <tt>nil</tt> if the variable is not bound.  The <i>value</i>&nbsp; of a quote is the
 first argument of the quote.  The value of an <tt>IF</tt>-expression depends on
 the value, <i>v</i>, of the first argument.  If <i>v</i>&nbsp; is <tt>nil</tt>, the value of the
 <tt>IF</tt>-expression is the value of its third argument; otherwise, it is the
 value of its second argument.
 </p>

 <p>
 Define these concepts.
 </p>

 <p>
 <b>Problem 133. <br/></b> An expression is said to be in <i><tt>IF</tt>-normal form</i>&nbsp; if no
 <tt>IF</tt>-expression in the expression has an <tt>IF</tt>-expression in its first
 argument.  Thus, <tt>(IF A (IF B C D) D)</tt> is in <tt>IF</tt>-normal form,
 but <tt>(IF (IF A B 'NIL) C D)</tt> is not.  It is possible to put an
 expression into <tt>IF</tt>-normal form while preserving its value, by
 repeatedly transforming it with the rule:
 <code>
 (IF (IF a b c) x y) = (IF a (IF b x y) (IF c x y))
 </code>
 </p>

 <p>
 Define the notion of <tt>IF</tt>-normal form and admit the function
 <tt>norm</tt> that normalizes an expression while preserving its value.
 </p>

 <p>
 <b>Problem 134. <br/></b> Given an expression in <tt>IF</tt>-normal form, define the function <tt>tautp</tt>
 that explores all feasible branches through the expression and determines
 that every output is non-<tt>nil</tt>.  We say a branch is <i>infeasible</i>
 if, in order to traverse it during evaluation under an assignment,
 the assignment would have to assign some variable both <tt>nil</tt> and
 non-<tt>nil</tt>.
 </p>

 <p>
 <b>Problem 135. <br/></b> Define <tt>tautology-checker</tt> to recognize whether an expression has
 a non-<tt>nil</tt> value under all possible assignments.
 </p>

 <p>
 <b>Problem 136. <br/></b> Prove that your <tt>tautology-checker</tt> is <i>sound</i>:  if it
 says an expression is a tautology, then the value of the expression
 is non-<tt>nil</tt>, under any assignment.
 </p>

 <p>
 <b>Problem 137. <br/></b> Prove that your <tt>tautology-checker</tt> is <i>complete</i>:
 if it fails to recognize an expression, then some assignment
 falsifies the expression.
 </p>

 <p>This concludes <i>Recursion and Induction</i>.  Are you interested in learning how
 to use the ACL2 theorem prover?  (Maybe explore &lt;&lt;@(see
 introduction-to-the-theorem-prover)&gt;&gt;?)</p>

 <p>Next: <see topic='@(url r-and-i-annotated-bibliography)'>Annotated Bibliography</see> (or <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>)</p>")
other
(defxdoc r-and-i-annotated-bibliography
  :parents (recursion-and-induction)
  :short "Recursion and Induction: Annotated Bibliography"
  :long "
 <h3>Annotated Bibliography</h3>

 <p>The following resources are useful for understanding the ACL2 logic and
 theorem prover, as well as its relation to both the earlier Nqthm logic and
 the Common Lisp programming language.  These resources are not necessary for
 you to do the exercises in these notes.  But if you are considering learning
 how to use the ACL2 or just wondering why anyone would bother, you might
 browse this annotated bibliography.</p>

 <ul>

 <li>[0] R. S. Boyer and J S. Moore.<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i>A Computational Logic Handbook</i>.<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Academic Press, London, 1997 (Second Edition).<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;See <i><a href='https://www.cs.utexas.edu/users/boyer/ftp/nqthm/'>https://www.cs.utexas.edu/users/boyer/ftp/nqthm/</a></i><br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for source code and regression suite<br/><br/>

 This book is the user's manual for the Boyer-Moore theorem prover, Nqthm, of
 the 1980s.  The ACL2 project started in 1989, when Boyer and Moore set
 themselves the goal of re-implementing Nqthm so that it supported an efficient,
 functional (applicative) subset of Common Lisp and was coded in that same subset.
 (They almost succeeded but had to use imperative code to implement functional
 versions of some utilities.)  So this reference, [0], describes the precursor
 of ACL2.  This book is the second edition of the Nqthm manual which was first
 published in 1988.  The url above contains the Nqthm source code and input and
 output files for the prover.  Most of these files were developed by the Nqthm
 user community.  The files include many proofs of classic list-processing and
 elementary number theory theorems but also proofs of Goedel's incompleteness
 theorem, Gauss's law of quadratic reciprocity, the Paris-Harrington Ramsey
 theorem, and the &ldquo;verified stack&rdquo; of Computational Logic, Inc.  The
 verified stack, first reported in 1989 and then ported to a verified fabricated
 microprocessor in 1992, consisted of a gate-level implementation of
 a microprocessor, an assembler, linker, and loader, a compiler, an
 operating system, and some applications, all of which were verified with Nqthm
 to &ldquo;stack&rdquo; so that a theorem proved about an application written
 in one of two high level languages and proved correct with respect to that
 high-level semantics runs correctly on the microprocessor.  These results are
 only briefly mentioned in [0] but that book does contain citations that
 describe them in detail.  Further development of Nqthm was halted because
 Nqthm users were building formal models that were so big they strained the
 capacity of the prover and were too slow to run as simulators for the modeled
 systems.  For example, when the ACL2 project was getting started, a student of
 Boyer was formalizing the Motorola 68020 microprocessor with the goal of
 verifying the Berkeley C String Library.  (That Nqthm project was completed
 successfully in 1993 and the files are available at the url above.)</li><p/>

 <li>[1] M. Kaufmann, P. Manolios, and J S. Moore, editors.<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i>Computer-Aided Reasoning: ACL2 Case Studies</i>.<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Kluwer Academic Press, Boston, MA., 2000.<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;See <i><a href='https://www.cs.utexas.edu/users/moore/publications/acl2-books/acs/index.html'>https://www.cs.utexas.edu/users/moore/publications/acl2-books/acs/index.html</a></i>.<br/><br/>

 This book is a collection of papers by ACL2 users, assembled in 2000,
 describing, in a textbook-like style. applications of ACL2.  It contains
 examples from graph theory, calculus, model checking, language simulators,
 microprocessor design including hardware description languages, floating-point
 implementations, compiler verification, and other topics.  While the Kluwer
 hardback edition of the book is out of print, the url above includes
 instructions for obtaining a paperback copy (for which the authors of [1] and
 [2] hold the copyright).</li><p/>

 <li>[2] M. Kaufmann, P. Manolios, and J S. Moore.<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i>Computer-Aided Reasoning: An Approach</i>.<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Kluwer Academic Press, Boston, MA., 2000.<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i><a href='https://www.cs.utexas.edu/users/moore/publications/acl2-books/car/index.html'>https://www.cs.utexas.edu/users/moore/publications/acl2-books/car/index.html</a></i>.<br/><br/>

 This book is essentially a textbook for students wishing to learn how to use
 the ACL2 system.  It starts with a description of the ACL2 programming
 language, then formalizes the logic with axioms and rules of inference, and
 then discusses how to prove theorems with the system.  The book includes
 exercises.  While the Kluwer hardback edition of the book is out of print, the
 url above includes instructions for obtaining a paperback copy (for which the
 authors of [1] and [2] hold the copyright).</li><p/>

 <li>[3] M. Kaufmann and J S. Moore.<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A precise description of the ACL2 logic.<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;In <i> <a
   href='https://www.cs.utexas.edu/users/moore/publications/km97a.pdf'>https://www.cs.utexas.edu/users/moore/publications/km97a.pdf</a></i><br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Dept. of Computer Science, University of Texas at Austin, 1997.<br/><br/>

 The title says it all.  The ACL2 logic is a first-order
 logic of total recursive functions providing mathematical
 induction and several extension principles including symbol package definition
 and recursive function definition.  The logic is a formalization of an
 extension of a functional subset of Common Lisp.  This paper describes the
 logic in detail, more in the style of a logic book than the style used in
 these notes.  The paper also explains the connection between theorems in the
 logic and evaluation in Common Lisp, which very roughly speaking is that,
 given enough time and computing resources, any instance of a
 guard-verified (aka a &ldquo;gold&rdquo; theorem in the terminology of this
 1997 paper) will compute to non-@('nil') in Common Lisp.
 (Maybe explore &lt;&lt;@(tsee verify-guards)&gt;&gt;?)</li><p/>

 <li>[4] M. Kaufmann and J S. Moore.<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The ACL2 home page.<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i><a href='http://www.cs.utexas.edu/users/moore/acl2/'>http://www.cs.utexas.edu/users/moore/acl2/</a></i><br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Dept. of Computer Science, University of Texas at Austin, 2022.<br/><br/>

 This web page contains the latest release of the ACL2 system in Common Lisp
 source code form.  The system is largely implemented in the subset of Common
 Lisp the prover supports.  ACL2 is distributed without fee under a 3-clause
 BSD license.  A new release is currently made about once per year and the web
 page also contains links to all past releases going back to 1996.  The home
 page includes instructions for installing any of several Common Lisp
 implementations and instructions for downloading and building ACL2.  The web
 page contains the online user's manual and instructions for how to download
 the regression suite from <a href='https://github.com/acl2/acl2'>the ACL2
 GitHub repository</a>.  The regression suite, called the ACL2 &lt;&lt;@(see
 Community-Books)&gt;&gt;, contains thousands of verified files created by the
 ACL2 user community containing definitions and theorems.  If you scan down to
 the <b>Subtopics</b> section of the &lt;&lt;@(see TOP)&gt;&gt; node of the
 manual you will find a list of many topics for which certified &lt;&lt;@(see
 books)&gt;&gt; are available.  To take just one example from that top-level
 list of Subtopics, scroll down to Hardware Verification.  In that Subtopic you
 find directories dealing with symbolic simulation, register transfer
 logic (including tools for reasoning about floating point implementations), a
 Verilog translator, an x86 ISA model, and many other topics.  There are many
 other nodes besides Hardware Verification.  In fact, the tree of books listed
 among the Subtopics is simply too big and too rapidly changing to try to
 summarize here.  We encourage you to explore, or ask &lt;&lt;@(see
 ACL2-help)&gt;&gt; about resources (if any) for a particular topic.</li><p/>

 <li>[5] P. Manolios and D. Vroon.<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ordinal arithmetic in acl2.<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;In <i>ACL2 Workshop 2003</i>, Boulder, Colorado, July 2003.<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='http://www.cs.utexas.edu/users/moore/acl2/workshop-2003/'>http://www.cs.utexas.edu/users/moore/acl2/workshop-2003/</a>.<br/><br/>

 The termination of recursive functions in ACL2 and the induction principle are
 both based on the ordinals and the well-foundedness of ordinal &ldquo;less
 than&rdquo;.  The description of ACL2 in [2] above includes a formalization of
 the ordinals up to &epsilon;_0 (&ldquo;epsilon naught&rdquo;) represented in
 ACL2 with conses and natural numbers based on a version of Cantor Normal Form.
 That representation was superseded in 2004 by the representation described in
 this paper, which implements a slightly different version of the normal form
 that is exponentially more efficient.  The paper also describes algorithms for
 manipulating ordinals in this representation.</li><p/>

 <li>[6] K. Pitman (editor).<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i>Common Lisp Hyper Spec</i>.<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LispWorks, Ltd, 1996.<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='http://www.lispworks.com/documentation/HyperSpec/Front/'>http://www.lispworks.com/documentation/HyperSpec/Front/</a>.<br/><br/>

 This is an online hypertext presentation of the Common Lisp specification as described in [7].</li><p/>

 <li>[7] G. L. Steele, Jr.<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i>Common Lisp The Language, Second Edition</i>.<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Digital Press, 30 North Avenue, Burlington, MA.  01803, 1990.<br/><br/>

 This is the definitive specification of Common Lisp.  ACL2 only formalizes a
 small subset of the language described by Steele.  But ACL2's documentation of
 some primitives refers to Steele's descriptions.  By the way, we do not
 recommend the ACL2 documentation as a way to learn to how to program in full
 Common Lisp.  Indeed, we don't recommend [6] or [7] for that purpose either.
 Many good introductions to Common Lisp are available via the web.  There are
 many implementations of Common Lisp available and the @(see installation)
 instructions list several; see @(see obtaining-common-lisp).</li>

 <li>[8] W. A. Hunt, Jr., M. Kaufmann, J S. Moore and A. Slobodova.<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Industrial Hardware and Software Verification with ACL2.<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;In <i>Verified Trustworthy Software Systems</i>, P. Gardner, P. O'Hearn, M. Gordon,<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;G. Morrisett and F. B. Schneider, Phil. Trans. R. Soc. A, <b>375</b>, The Royal Society,<br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ISSN 1364-503X, DOI 10.1098/rsta.2015.0399 (Article Number 20150399), 2017.<br/><br/>

 The ACL2 system has seen sustained industrial use since the
 mid-1990s. Companies that have used ACL2 regularly include AMD, Centaur
 Technology, IBM, Intel, Kestrel Institute, Motorola/Freescale, Oracle and
 Collins (formerly Rockwell Collins).  This paper describes how ACL2 came to be used in industry,
 what it is used for, and how it is used.  The paper highlights ACL2's use in
 the microprocessor industry, specifically by Centaur Technology on modules in
 their x86 microprocessors.  The paper was written in 2017.  Since then the
 formal verification team at Centaur Technology has moved to Intel,
 where ACL2 is used in the same way today (2022).</li><p/>

 </ul>

 <see topic='@(url r-and-i-table-of-contents)'>Table of Contents</see>")
other
(order-subtopics recursion-and-induction
  (r-and-i-introduction r-and-i-data-types
    r-and-i-terms
    r-and-i-substitutions
    r-and-i-abbreviations-for-terms
    r-and-i-function-definitions
    r-and-i-axioms
    r-and-i-terms-as-formulas
    r-and-i-definitions-revisited
    r-and-i-structural-induction
    r-and-i-arithmetic
    r-and-i-inadequacies-of-structural-recursion
    r-and-i-ordinals
    r-and-i-definitional-principle
    r-and-i-induction-principle
    r-and-i-relations-between-recursion-and-induction
    r-and-i-more-problems
    r-and-i-more-inadequacies-of-the-definitional-principle
    r-and-i-still-more-problems
    r-and-i-annotated-bibliography))
other
(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>")
other
(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>")
other
(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).  It also 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>Note that undoing a @(':redef+') command, say with @(':')@(tsee u), only
 undoes the effects of @(':redef+') on the ACL2 @(see world); it does
 <i>not</i> undo the other effects on the ACL2 @(see state).  The best way to
 undo the effects of @(':redef+') is generally to execute @(':')@(tsee redef-).
 To understand this point we look at the code for @('redef+').  The output
 below has been edited to put world-changing parts in lower case.</p>

 @({
 ACL2 !>:trans1 (redef+)
  (WITH-OUTPUT
       :OFF (SUMMARY EVENT)
       (PROGN (defttag :redef+)
              (PROGN! (SET-LD-REDEFINITION-ACTION '(:WARN! . :OVERWRITE)
                                                  STATE)
                      (program)
                      (SET-TEMP-TOUCHABLE-VARS T STATE)
                      (SET-TEMP-TOUCHABLE-FNS T STATE)
                      (F-PUT-GLOBAL 'REDUNDANT-WITH-RAW-CODE-OKP
                                    T STATE)
                      (set-state-ok t))))
 ACL2 !>
 })

 <p>In particular, we see that redefinition remains active after undoing.  In
 general, it is therefore best to execute @(':redef-') before undoing
 @(':redef+').</p>

 <p>This @(see command) was introduced to support modification of ACL2 source
 code definitions.  Thus, note that even system functions can be redefined with
 a mere warning.  Be careful!</p>")
other
(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>")
other
(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>")
other
(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>")
other
(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, where those arguments are not evaluated.</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)') or if you have disabled the default
 ``soft'' interrupt behavior (see @(see abort-soft)).</p>")
other
(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 @('std/testing/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 ...)'), with the exception
 noted below; 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>The second condition has the following exception: it does not apply when
 the new @('encapsulate') event takes place within an @(tsee include-book)
 event.  (Allowing that would be unsound, as explained in a comment in ACL2
 source function @('corresponding-encaps').)</p>

 <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>")
other
(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 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 defstobj) or @(tsee defabsstobj) is redundant if there is already
 an identical such event in the logical @(see world).</p>

 <p>A @(tsee defattach) event is never redundant.  (Reasons are provided in a
 comment in the ACL2 sources definition of defattach in the ACL2 logic.)  Note
 that @('defattach') events do not define any names.</p>

 <p>A @(tsee defaxiom) or @(tsee defthm) event is redundant if there is already
 an axiom or theorem of the given name and the two @(see events) are
 syntactically identical.  But there is the following more generous criterion,
 which applies unless the older event is a @('defthm') event and the newer
 event is a @('defaxiom') event: both the formula (after macroexpansion) and
 the @(see rule-classes) (after translation and certain ``truncation'') are
 syntactically identical.  This ``truncation'' involves removing the
 @(':HINTS') and @(':INSTRUCTIONS') fields from a rule-class, and also removing
 the @(':COROLLARY') field when it specifies the same term as the event.  Note
 that a @(tsee defthm) can be redundant with a @(tsee defaxiom) but not
 vice-versa.  (Remark for system hackers: @('defthm')/@('defaxiom') redundancy
 is implemented in ACL2 source function, @('redundant-theoremp').)</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 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'), @(':type-prescription'), @(':')@(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>

 <li>The @(see stobj)s declared by the two definitions are allowed to disagree
 on @('state'): one can declare @('state') among its declared @(':stobjs')
 values while the other does not, regardless of whether or not @(tsee
 set-state-ok) has been evaluated.  That is, they only need to agree on the
 stobjs that are <i>user-defined</i>.</li>

 <li>Redundancy may fail with an error about a name being &ldquo;already
 defined using special raw Lisp code&rdquo; or &ldquo;predefined in the
 "COMMON-LISP" package&rdquo;.  This applies to certain functions that are
 built into ACL2; it may also apply when definitions are overridden in raw Lisp
 using trust tags (see @(see defttag)), typically in books.  The reason for
 causing an error is that if the proposed redundant definition is in a book,
 then when later including that book after it is certified, the compiled code
 for that definition will replace the original code, which is generally
 undesirable when the original code has special raw Lisp optimizations.  If the
 earlier definition is in a book, then the error message will suggest including
 that book rather than trying to define the function redundantly.</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 by default, though that can
 be changed; see @(see set-in-theory-redundant-okp).  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).  Setting a non-existent key to @('nil') is not redundant, with the
 exception discussed next.</p>

 <p>@(csee Memoization) is carried out using a @(see table),
 @('memoize-table'), that may associate a function symbol with @('nil') when it
 is not memoized.  It is redundant to @(tsee unmemoize) a currently-unmemoized
 function symbol, thus associating it with @('nil') in the @('memoize-table')
 &mdash; even if that function symbol is not already a key of that table (this
 is the exception noted in the preceding paragraph).  It is redundant to @(tsee
 memoize) a function when the function is already identically memoized, that
 is, when the corresponding @(tsee table) event is redundant.</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,
 user-defined 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))
 })")
other
(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>A rewrite rule may fail to fire because its equivalence relation is not
 known to be a refinement of any of those known to be permitted.  See @(tsee
 geneqv) for a discussion of how ACL2 uses @(tsee congruence) rules to derive
 the permitted equivalences and how those equivalences are represented.  See
 @(see refinement-failure) for advice on how to use @(see break-rewrite) to
 determine that a rule failed the refinement check and for advice about how to
 ``fix'' such a problem.</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.  Furthermore, @(':refinement')
 lemmas are not tracked and are thus not reported in the @(see summary).  Of
 course, individual @(':')@(tsee rewrite) rules can be disabled.</p>

 <p>More will be written about this as we develop the techniques.</p>")
other
(defxdoc refinement-failure
  :parents (introduction-to-the-theorem-prover break-rewrite)
  :short "what to do when a rewrite rule fails the refinement check"
  :long "<p>One reason a @(':')@(tsee rewrite) rule may fail to fire is that
  its equivalence relation fails to be a known refinement of the generated
  equivalence relation (or ``@(see geneqv)'') governing the current target of the
  rewriter.  In the following discussion we assume you are familiar with the
  notion of the generated equivalence relation.  If not, please see @(tsee
  geneqv) for the necessary background and details.</p>

  <h3>Is a Rule Not Firing Because of a Refinement Failure?</h3>

  <p>To determine whether refinement failure is the cause of a rule's failure
  to fire, enable @(see break-rewrite) with @('(brr t)') and install a @(tsee
  monitor) with @(':rf') set to @('t') on the rule, e.g., @('(monitor rune
  '(:rf t))'), where @('rune') evaluates to the @(tsee rune) of the rule in
  question.  You might also specify a @(':condition') so that a break occurs
  only if the target is the translated term, @('tterm'), you expected the rule
  to hit,</p>

  @({
  (monitor rune '(:condition (equal (brr@ :target) 'tterm) :rf t)).
  })

  <p>Then try the proof again.  (Note: if the rule being monitored is a @(see
  simple) abbreviation rule, be sure to supply the hint @(':DO-NOT
  '(PREPROCESS)') as discussed in @(tsee monitor).)  If a monitored rule fails
  to fire (under the monitored condition) because its equivalence relation is
  not known to refine the geneqv derived for that occurrence of the target, an
  interactive break will occur.  The break header will name the rule, print the
  target, show the rule's equivalence relation, and show the geneqv.  The
  header tells you the equivalence relation is not a refinement of the geneqv.
  You might wish to use the break-rewrite command @(':path') or @(':path+') to
  print the path down to the target from the top-level goal.  That will show
  the geneqv derived for each active call of the rewriter and will help you
  understand why the current geneqv is what it is.  While looking at the path
  make sure that the current occurrence of the target is the one you expected
  the rule to hit.  If it is not, proceed to the next break with @(':ok').</p>

  <p>When you find the target you're looking for, focus your attention on the
  equivalence relation and geneqv.  To fix the problem you need the former to
  be a refinement of the latter.  When you understand how to make that happen,
  abort the failing proof attempt with @(':a!') and try to fix the problem.</p>

  <h3>How to Fix a Refinement Failure</h3>

  <p>There are two basic ways to ``fix'' a refinement failure:</p>

  <ul>

  <li>(a) prove a @(tsee refinement) rule that establishes that the
  equivalence relation used in the rule indeed refines one of the equivalence
  relations displayed in the geneqv, or</li>

  <li>(b) prove a @(tsee congruence) rule that will extend the geneqv
  derived for the current occurrence of the target.</li>

  </ul>

  <p>We illustrate these approaches below.  But first you must keep in mind
  that the equivalence relation in the rule may not refine any possible geneqv
  derivable along the path.  You may have to find a different proof or, at
  least, you may have to define some additional equivalence relations,
  refinement rules, and congruence rules, and prove a version of your lemma
  that uses a new relation.  After all, this is a theorem proving problem and
  not all fixes are trivial!</p>

  <h3>How Geneqvs Are Displayed</h3>

  <p>As illustrated in the discussion of @(see geneqv), a generated equivalence
  is essentially a set of equivalence relations.  ACL2 prints geneqvs in three
  different ways depending on the utility doing the printing.</p>

  <p>When reporting that an equivalence relation is not a refinement of a
  geneqv, the geneqv is printed simply as a list of equivalence relation names,
  e.g., @('(EQV1 EQV2)').  Order is unimportant as this list represents a
  set.</p>

  <p>When reporting the path the rewriter took to the current target and the
  geneqvs for each active call of the rewriter along that path, each geneqv is
  printed as a list of doublets, where the first component of the doublet is
  the name of an equivalence relation and the second component is the name of
  the @(see congruence) rule responsible for adding that relation to the
  geneqv, e.g.,</p>

  <code>
  ((EQV1 EQV1-IFF-CONGRUENCE-FOR-F)
   (EQV2 EQV2-IFF-CONGRUENCE-FOR-F))
  </code>

  <p>This is just another presentation of @('(eqv1 eqv2)') but we believe
  the congruence rule names may help you recall how equivalence relations get
  into the set.</p>

  <p>Finally, in @(tsee trace$), or the value returned by (brr@ :geneqv) or any
  other system utility that displays the actual internal representation of a
  geneqv you will see something like this:</p>

  <code>
  ((5603 EQV1 . (:congruence EQV1-IFF-CONGRUENCE-FOR-F))
   (4957 EQV2 . (:congruence EQV2-IFF-CONGRUENCE-FOR-F)))
  </code>

  <p>where the equivalence relation names are paired with the runes (not just the names)
  of the responsible congruence rules and the numbers are unique session-dependent indices
  for those runes allowing quick determination of the enabled status of the rules.</p>

  <p>You will see the first two print conventions in the examples below.</p>

  <h3>Some Generic Examples</h3>

  <p>In the following discussion we introduce some functions that will allow us
  to explore refinement failures.  The experiments reported below are carried
  out in the community book @('books/demos/refinement-failure-test-book.lisp')
  whose input/output log may be found in
  @('books/demos/refinement-failure-test-log.txt').</p>

  <p>We're going to attempt to prove @('(P (F (G A (BETA B))))') by rewriting
  the occurrence of @('(BETA B)') to @('(GAMMA B)') and appealing to a rule
  that establishes @('(P (F (G A (GAMMA B))))').  But at every subterm level in
  the conjecture different equivalence relations are involved.  Thus, many
  equivalence and congruence relations are involved and that makes this example
  hard to follow.  Assume that @('PEQ'), @('FEQ'), @('G2EQ1'), @('G2EQ2'), and
  @('G2EQ1!') are known equivalence relations.</p>

  <p>Possibly Distracting Aside: In this section of this documentation we use
  names that follow a certain convention.  These conventions help the authors
  keep the names straight!  Perhaps they'll help you too.  Names containing
  ``@('EQ')'' are equivalence relations; they will serve as ``inside''
  equivalences for the function symbol indicated by the first character in the
  name, ``@('P')'', ``@('F')'' or ``@('G')''; if that first character is
  followed by ``2'' it means they apply to the second argument of the function,
  otherwise they apply to the first (and only) argument; and if there is more
  than one such inside equivalence relation for that function the name is
  suffixed with ``@('1')'' or ``@('2')''.  The exclamation mark at the end of
  ``G2EQ1!'' is to remind us that the function is a refinement of @('G2EQ1').
  Thus @('PEQ') is the inside equivalence for the first (only) argument of
  @('P')-terms and @('G2EQ1') is the inside equivalence for the second argument
  of @('G')-terms and is one of two such relations.</p>

  <p>Imagine that we've proved two rewrite rules:</p>

  <ul>

  <li>@('(DEFTHM RULE (G2EQ1! (BETA X) (GAMMA X)))')</li>

  <li>@('(DEFTHM DONE (P (F (G X (GAMMA Y)))))')

      <p>which is actually stored as</p>

     @('(DEFTHM DONE (IFF (P (F (G X (GAMMA Y)))) T))').</li>

  </ul>

  <p>Clearly, our strategy to prove @('(P (F (G A (BETA B))))') is to use
  @('RULE') to replace the @('(BETA B)') by @('(GAMMA B)'), and then use
  @('DONE') to reduce the conjecture to @('T').</p>

  <p>However, the problem is that @('RULE') uses the equivalence relation
  @('G2EQ1!').  So the rewriter, which starts by maintaining @('IFF') on the
  top-level @('P') term, will have to evolve a geneqv so that by the time it
  reaches the occurrence of @('(BETA B)') the geneqv at that target admits
  @('G2EQ1!') as a refinement.  To do so we'll provide the following @(tsee
  congruence) rules.  As you read them, remember that the term we'll be working
  on is @('(P (F (G A (BETA B))))'), i.e., our conjecture is a call of @('P'),
  in which the 1st (and only) argument is a call of @('F'), in which the 1st
  (and only) argument is a call of @('G'), in which the 2nd argument is call of
  @('BETA').</p>

  <ul>

  <li>@('IFF') is maintained on a call of @('P') provided @('PEQ') is maintained on
  the 1st argument of @('P'):
    <ul>
    <li><i>event</i>:  @('(DEFCONG PEQ IFF (P X) 1)')</li>
    <li><i>name</i>: @('PEQ-IMPLIES-IFF-P-1')</li>
    </ul>
    </li>

  <li>@('PEQ') is maintained on a call of @('F') provided @('FEQ') is maintained on
  the 1st argument of @('F'):
    <ul>
    <li><i>event</i>:  @('(DEFCONG FEQ PEQ (F X) 1)')</li>
    <li><i>name</i>: @('FEQ-IMPLIES-PEQ-F-1')</li>
    </ul>
    </li>

  <li>@('FEQ') is maintained on a call of @('G') provided @('G2EQ1') is maintained on
  the 2nd argument of @('G'):
    <ul>
    <li><i>event</i>:  @('(DEFCONG G2EQ1 FEQ (G X Y) 2)')</li>
    <li><i>name</i>: @('G2EQ1-IMPLIES-FEQ-G-2')</li>
    </ul>
    </li>

  <li>@('FEQ') is <i>also</i> maintained on a call of @('G') provided @('G2EQ2') is maintained on
  the 2nd argument of @('G'):
    <ul>
    <li><i>event</i>:  @('(DEFCONG G2EQ2 FEQ (G X Y) 2)')</li>
    <li><i>name</i>: @('G2EQ2-IMPLIES-FEQ-G-2')</li>
    </ul>
    </li>

  </ul>

  <p>Note that there are two ways to maintain @('FEQ') on a call of @('G'):
  maintain either @('G2EQ1') or @('G2EQ2') on the second argument of @('G').
  But neither of those equivalence relations is used in our rewrite @('RULE').
  Our @('RULE') uses @('G2EQ1!'), so assume we've proved:</p>

  <ul>

  <li>@('G2EQ1!') refines @('G2EQ1'):
    <ul>
    <li><i>event</i>: @('(DEFREFINEMENT G2EQ1! G2EQ1)')</li>
    <li><i>name</i>: @('G2EQ1!-REFINES-G2EQ1')</li>
   </ul>
   </li>

  </ul>

  <p>Having arranged all of the above, imagine issuing the commands</p>

  @({
  (brr T)
  (monitor '(:REWRITE RULE)
           '(:condition (and (equal (brr@ :target) '(BETA B))
                             '(:path+ :go))
             :rf t))
  (thm (P (F (G A (BETA B))))
       :hints (("Goal" :do-not '(preprocess))))
  })

  <p>Note: The @(':condition') value above will cause a break only if the
  @(':target') is @('(BETA B)'), but when the break occurs it will issue the
  command @(':PATH+') to print the path and then issue the command @(':GO') to
  proceed from the break.  Because we've just monitored a @(see simple)
  abbreviation rule, we include in the @(tsee thm) command the hint to avoid
  preprocessing, as advised in the documentation for @(tsee monitor).</p>

  <p>Because we've done the equivalence, congruence, and refinement setup
  perfectly, our @('RULE') will fire and we will get a break like this:</p>

  @({
  (1 Breaking (:REWRITE RULE) on (BETA B):
  1 ACL2 >
  })

  <p>The subsequent @(':PATH+') command will show how the rewriter descended to
  here from the top-level goal and will display the geneqvs derived for each
  rewrite.</p>

  @({
  1 ACL2 >:path+
  1. Simplifying the clause
       ((P (F (G A (BETA B)))))
  2. Rewriting (to simplify) the atom of the first literal,
       (P (F (G A (BETA B)))),
     Geneqv: (IFF)
  3. Rewriting (to simplify) the first argument,
       (F (G A (BETA B))),
     Geneqv: ((PEQ PEQ-IMPLIES-IFF-P-1))
  4. Rewriting (to simplify) the first argument,
       (G A (BETA B)),
     Geneqv: ((FEQ FEQ-IMPLIES-PEQ-F-1))
  5. Rewriting (to simplify) the second argument,
       (BETA B),
     Geneqv: ((G2EQ2 G2EQ2-IMPLIES-FEQ-G-2)
              (G2EQ1 G2EQ1-IMPLIES-FEQ-G-2))
  6. Attempting to apply (:REWRITE RULE) to
       (BETA B)
     Preserving: G2EQ1!
     Geneqv: ((G2EQ2 G2EQ2-IMPLIES-FEQ-G-2)
              (G2EQ1 G2EQ1-IMPLIES-FEQ-G-2))
  1 ACL2 >
  })

  <p>Recall, from the discussion above, that sometimes geneqvs are printed
  merely as a list of equivalence relations, e.g., @('(G2EQ2 G2EQ1)'), and
  other times, as above, are printed so as to include the name of the
  congruence relation responsible for each equivalence.</p>

  <p>Notice that in frame 4, where the rewriter is working on @('(G A (BETA
  B))') it is to maintain the @('FEQ') equivalence relation (which was
  justified from frame 3 by the rule @('FEQ-IMPLIES-PEQ-F-1') where the
  rewriter was to maintain @('PEQ')).  But when the rewriter stepped from frame
  4 to the second argument of @('(G A (BETA B))') in frame 5, it used both
  @('G2EQ1-IMPLIES-FEQ-G-2') and @('G2EQ2-IMPLIES-FEQ-G-2') to derive the
  geneqv @('(G2EQ2 G2EQ1)').  Then, when it attempted to apply @('RULE'), whose
  equivalence relation is @('G2EQ1!'), it passed the refinement test because
  @('G2EQ1!') refines @('G2EQ1'), which is one of the equivalences listed in
  the geneqv.</p>

  <p>When we proceed from the break, the proof completes successfully.</p>

  <p>But now imagine that we had failed to prove @('(DEFREFINEMENT G2EQ1!
  G2EQ1)').  The @('thm') command above would have caused this break:</p>

  @({
  (1 Breaking (:REWRITE RULE) on (BETA B):

  The equivalence relation, G2EQ1!, of this rule is not a refinement
  of the current geneqv, (G2EQ2 G2EQ1).  Use :path or :path+ to see how
  the geneqv evolved.  See :DOC refinement-failure for advice about how
  to deal with this kind of problem.

  1 ACL2 >
  })

  <p>The break header explains the problem: the rewriter does not know that
  @('G2EQ1!') refines @('G2EQ1') or @('G2EQ2').  Of course, <i>we</i> do know
  that and the fix is simply to prove the ``forgotten'' @(tsee
  defrefinement).</p>

  <p>On the other hand, suppose we had proved the @('defrefinement') but had
  forgotten to prove that @('FEQ') is maintained on a call of @('G') when
  @('G2EQ1') is maintained on the 2nd argument of @('G'), i.e., @('(DEFCONG
  G2EQ1 FEQ (G X Y) 2)'), aka @('G2EQ1-IMPLIES-FEQ-G-2').  Then the @('thm')
  command would produce the following break.</p>

  @({
  (1 Breaking (:REWRITE RULE) on (BETA B):

  The equivalence relation, G2EQ1!, of this rule is not a refinement
  of the current geneqv, (G2EQ2).  Use :path or :path+ to see how the
  geneqv evolved.  See :DOC refinement-failure for advice about how to
  deal with this kind of problem.
  })

  <p>Note that the geneqv is printed in its simplest form, as a list of
  equivalence relation names; in this case only one name is included:
  @('G2EQ2').  Of course, if we believed @('G2EQ1!') does refine @('G2EQ2'), it
  would suffice to prove the corresponding refinement rule.  But let's suppose
  we know @('G2EQ1!') doesn't refine @('G2EQ2').  Instead, we know @('G2EQ1!')
  refines @('G2EQ1'), which is not in the geneqv.  Our problem then is to
  arrange for @('G2EQ1') to be in the geneqv.  Look at the path that got us
  here.</p>

  @({
  1 ACL2 >:path+
  1. Simplifying the clause
       ((P (F (G A (BETA B)))))
  2. Rewriting (to simplify) the atom of the first literal,
       (P (F (G A (BETA B)))),
     Geneqv: (IFF)
  3. Rewriting (to simplify) the first argument,
       (F (G A (BETA B))),
     Geneqv: ((PEQ PEQ-IMPLIES-IFF-P-1))
  4. Rewriting (to simplify) the first argument,
       (G A (BETA B)),
     Geneqv: ((FEQ FEQ-IMPLIES-PEQ-F-1))
  5. Rewriting (to simplify) the second argument,
       (BETA B),
     Geneqv: ((G2EQ2 G2EQ2-IMPLIES-FEQ-G-2))
  6. Attempting to apply (:REWRITE RULE) to
       (BETA B)
     Preserving: G2EQ1!
     Geneqv: ((G2EQ2 G2EQ2-IMPLIES-FEQ-G-2))
  1 ACL2 >
  })

  <p>In frame 4 we are to maintain @('FEQ') on a call of @('G').  In frame 5 we
  are rewriting the second argument of @('G') and used
  @('G2EQ2-IMPLIES-FEQ-G-2') to derive the new geneqv containing @('G2EQ2').
  We could get @('G2EQ1') into that new geneqv is only we had a congruence rule
  that says @('FEQ') is maintained on @('G') when rewriting the second argument
  of @('G') maintaining @('G2EQ1').  That's just the ``forgotten'' @('(DEFCONG
  G2EQ1 FEQ (G X Y) 2)').  Of course we could alternatively have chosen to
  prove @('(DEFCONG G2EQ1! FEQ (G X Y) 2)'), but it is generally better to
  prove the strongest congruence rules we know.</p>

  <p>Finally, as documented in @(see refinement) and @(see congruence),
  refinement and congruence rules are not (always) tracked and usually do
  not show up in the @(see summary) printed at the end of proof attempts.
  The decision not to track every use of these rules was made to improve
  prover efficiency.</p>")
other
(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>")
other
(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>")
other
(defxdoc releases
  :parents (about-acl2)
  :short "ACL2 releases"
  :long "<p>The current ACL2 release on the <a
 href='http://www.cs.utexas.edu/users/moore/acl2/index.html'>ACL2 home page</a>
 is Version 8.6; see @(see note-8-6) for release notes.</p>

 <p>Below is a list of past releases and their corresponding past ACL2 home
 pages.  (Note: Some older versions of the manuals have been made unreadable to
 avoid potential security issues.)</p>

 <ul>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v8-5/index.html'>Version 8.5 (July, 2022)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v8-4/index.html'>Version 8.4 (August, 2021)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v8-3/index.html'>Version 8.3 (April, 2020)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v8-2/index.html'>Version 8.2 (May, 2019)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v8-1/index.html'>Version 8.1 (September, 2018)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v8-0/index.html'>Version 8.0 (December, 2017)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v7-4/index.html'>Version 7.4 (March, 2017)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v7-3/index.html'>Version 7.3 (December, 2016)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v7-2/index.html'>Version 7.2 (January, 2016)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v7-1/index.html'>Version 7.1 (May, 2015)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v7-0/index.html'>Version 7.0 (January, 2015)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v6-5/index.html'>Version 6.5 (August, 2014)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v6-4/index.html'>Version 6.4 (January, 2014)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v6-3/index.html'>Version 6.3 (October, 2013)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v6-2/index.html'>Version 6.2 (June, 2013)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v6-1/index.html'>Version 6.1 (February, 2013)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v6-0/index.html'>Version 6.0 (December, 2012)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v5-0/index.html'>Version 5.0 (August, 2012)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v4-3/index.html'>Version 4.3 (July, 2011)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v4-2/index.html'>Version 4.2 (January, 2011)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v4-1/index.html'>Version 4.1 (September, 2010)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v4-0/index.html'>Version 4.0 (July, 2010)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v3-6/new/v3-6-1/index.html'>Version 3.6.1 (September, 2009)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v3-6/index.html'>Version 3.6 (August, 2009)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v3-5/index.html'>Version 3.5 (May, 2009)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v3-4/index.html'>Version 3.4 (August, 2008)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v3-3/index.html'>Version 3.3 (November, 2007)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v3-2/new/v3-2-1/index.html'>Version 3.2.1 (June, 2007)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v3-2/index.html'>Version 3.2 (April, 2007)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v3-1/index.html'>Version 3.1 (December, 2006)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v3-0/new/v3-0-1/index.html'>Version 3.0.1 (August, 2006)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v3-0/index.html'>Version 3.0 (June, 2006)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v2-9/new/v2-9-4/index.html'>Version 2.9.4 (January, 2006)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v2-9/new/v2-9-3/index.html'>Version 2.9.3 (August, 2005)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v2-9/new/v2-9-2/index.html'>Version 2.9.2 (April, 2005)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v2-9/new/v2-9-1/index.html'>Version 2.9.1 (December, 2004)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v2-9/index.html'>Version 2.9 (October, 2004)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v2-8/index.html'>Version 2.8 (March, 2004)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v2-7/index.html'>Version 2.7 (November, 2002)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v2-6/index.html'>Version 2.6 (November, 2001)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v2-5/index.html'>Version 2.5 (June, 2000)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v2-4/index.html'>Version 2.4 (August, 1999)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v2-3/index.html'>Version 2.3 (October, 1998)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v2-2/index.html'>Version 2.2 (August, 1998)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v2-1/index.html'>Version 2.1 (December, 1997)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v2-0/index.html'>Version 2.0 (July, 1997)</a></li>
 <li><a href='http://www.cs.utexas.edu/users/moore/acl2/v1-9/acl2-doc.html'>Version 1.9 (Fall, 1996)</a></li>
 </ul>

 <p><b>Note</b>: The ACL2 Home Pages for versions between 5.0 and 7.0, listed
 above, did not directly include the Community Books, which were distributed
 separately.  You may find the books for those versions at <tt><a
 href='http://acl2.org/books-pre-7.0/'>http://acl2.org/books-pre-7.0/</a></tt>.</p>")
other
(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)")
other
(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>")
other
(defxdoc remove-assoc
  :parents (alists acl2-built-ins)
  :short "Remove all pairs with a given key from an association list"
  :long "@({
  General Forms:
  (remove-assoc key alist)
  (remove-assoc key alist :test 'eql)   ; same as above (eql as equality test)
  (remove-assoc key alist :test 'eq)    ; same, but eq is equality test
  (remove-assoc key alist :test 'equal) ; same, but equal is equality test
 })

 <p>@('(Remove-assoc key alist)') returns an alist that is the same as the list
 @('alist'), except that all pairs in @('alist') with a @(tsee car) of @('key')
 are deleted (if any; otherwise @('alist') is returned).  Note that the order
 of the elements of @('alist') is unchanged (though some may be deleted).</p>

 <p>Also see @(see remove1-assoc) for a similar utility that deletes only the
 first pair in an alist with a given key, rather than all such pairs.</p>

 <p>The @(see guard) for a call of @('remove-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
 @('remove-assoc') and its variants:</p>

 <blockquote><p>@('(remove-assoc-eq key alist)') is equivalent to
 @('(remove-assoc key alist :test 'eq)');</p>

 <p>@('(remove-assoc-equal key alist)') is equivalent to @('(remove-assoc key
 alist :test 'equal)').</p></blockquote>

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

 @(def remove-assoc-equal)")
other
(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>")
other
(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 @(see summary)
 but nevertheless changes the ACL2 logical @(see world) and is so
 recorded.</p>")
other
(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 @(see 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>")
other
(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>")
other
(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>")
other
(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>")
other
(defxdoc remove-global-stobj
  :parents (events stobj)
  :short "Remove a global @(see stobj) with a given name"
  :long "<p>See @(tsee add-global-stobj) for relevant background and
 terminology together with an explanation of @('remove-global-stobj').  Here we
 give only a brief summary.</p>

 @({
 General Form:
 (remove-global-stobj x state)
 })

 <p>where @('x') evaluates to the name of a stobj that has a global value.</p>

 @({
 Example Form:
 (remove-global-stobj 'st state)
 })")
other
(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 such
 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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(defxdoc remove-trivial-equivalences-enabled-p
  :parents (rewrite system-attachments)
  :short "Avoid removal of trivial equivalences during rewriting"
  :long "<p>This topic concerns an advanced control for the ACL2 prover.</p>

 <p>This zero-ary attachable system function controls the
 &ldquo;remove-trivial-equivalences&rdquo; heuristic, which uses an equality
 hypothesis (and, when appropriate, an @(see equivalence) hypothesis) to
 replace a variable by a term in the rest of the goal.  (However, perhaps
 similar heuristics will still be used, for example as part of the @(see
 tau-system).)  Attach the function @('constant-nil-function-arity-0') to avoid
 this heuristic, and attach the function @('constant-t-function-arity-0') to
 restore it.</p>")
other
(defxdoc remove-untouchable
  :parents (defttag)
  :short "Remove names from lists of untouchable symbols"
  :long "<p>Untouchables are functions that cannot be called or 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>")
other
(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>")
other
(defxdoc remove1-assoc
  :parents (alists acl2-built-ins)
  :short "Remove the first pair with a given key from an association list"
  :long "@({
  General Forms:
  (remove1-assoc key alist)
  (remove1-assoc key alist :test 'eql)   ; same as above (eql as equality test)
  (remove1-assoc key alist :test 'eq)    ; same, but eq is equality test
  (remove1-assoc key alist :test 'equal) ; same, but equal is equality test
 })

 <p>@('(Remove1-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>Also see @(see remove-assoc) for a similar utility that deletes all pairs
 in an alist with a given key, rather than only the first such pair.</p>

 <p>The @(see guard) for a call of @('remove1-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
 @('remove1-assoc') and its variants:</p>

 <blockquote><p>@('(remove1-assoc-eq key alist)') is equivalent to
 @('(remove1-assoc key alist :test 'eq)');</p>

 <p>@('(remove1-assoc-equal key alist)') is equivalent to @('(remove1-assoc key
 alist :test 'equal)').</p></blockquote>

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

 @(def remove1-assoc-equal)")
other
(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>")
other
(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>")
other
(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 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>")
other
(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').  See @(see disable-ubt) for a
 variant of @('(reset-prehistory t)') that does not change command numbering
 and is used by the @(see break-rewrite) utility.  Like @('disable-ubt'),
 @('reset-prehistory') is never @(see redundant).</p>")
other
(defxdoc resize-list
  :parents (stobj acl2-built-ins)
  :short "List resizer in support of @(see stobj)s"
  :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 defstobj).</p>

 @(def resize-list-exec)

 @(def resize-list)")
other
(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)")
other
(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>")
other
(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 extend-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 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>")
other
(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>")
other
(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 in most cases.  That
 binding is avoided only when the first argument is of the form @('(QUOTE S)')
 for @('S') a macro name and the second argument is a symbol or of the form
 @('(QUOTE X)') for any @('X').  By binding @('*aokp*') to @('t'), ACL2 is
 permitted to use attachments when evaluating 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 a symbol 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).
  ? (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
  ? (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))
  ?
 })

 <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 it may help to see :DOC raw-lisp-error.

  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).
  ? (macroexpand-1
     '(RETURN-LAST 'WITH-PROFILING-RAW
                   '(ASSOC-EQ FGETPROP REWRITE)
                   (MINI-PROVEALL)))
  (WITH-PROFILING-RAW '(ASSOC-EQ FGETPROP REWRITE) (MINI-PROVEALL))
  T
  ?
 })

 <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)') where @('F') is a
 non-@('nil') symbol, 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>For any object @('x') that is not of the form @('(quote S)') where @('S')
 is a symbol, the call @('(return-last x y z)') is legal, even in code, if
 @('y') and @('z') are legal.  Such terms are evaluated as though @('x') is
 @('(QUOTE PROGN)'), that is, as though they arose from a call of @(tsee
 prog2$).  In particular, you are welcome to write terms of the form
 @('(return-last '(<some-annotation>) y z)').</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>

 @({
  (defttag t)
  (set-raw-mode t)
  (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)))
  (set-raw-mode nil)
  (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 it may help to see :DOC raw-lisp-error.

  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)")
other
(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)
 or @(tsee macrolet).  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>")
other
(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)")
other
(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)")
other
(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 definition.</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>")
other
(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).  If you want a flexible, convenient
 interface to the ACL2 rewriter that can be called programmatically, see @(see
 rewrite$).</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 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))').)  During this flattening process, we eliminate @(tsee
 lambda)s as necessary in order to continue flattening; one may think of this
 step as simply substituting to eliminate @(tsee let), @(tsee let*), and @(tsee
 mv-let) in order to expose more calls of @('implies') and @('and').  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 we continue to eliminate @('lambdas') until we
 reach this form, and then we eliminate @('lambdas') from the first argument of
 @('equiv') but not the second argument.  Here @('equiv') is a known @(see
 equivalence) relation.  If we do not reach an equivalence relation, even after
 eliminating @('lambdas'), then we replace the resulting term, @('term') by
 @('(iff term t)'), except that we replace @('(not term)') by @('(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 and @('lhs') has no
 @('lambda')s.  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>You can experiment by creating some rewrite rules using @(tsee defthm) and
 then using @(':')@(tsee pr) to see how the rule was stored.</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 suggestion, above, that the rewriter looks through the goal @(see
 clause) for ``any instance of the @('lhs')'' is not quite true.  @(':Rewrite')
 rules are never applied to quoted constants or any term inside a call of
 @(tsee hide).  If you want to rewrite a quoted constant use a @(':')@(tsee
 rewrite-quoted-constant) rule.</li>

 <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 (binary-+ '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, 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 @(see double-rewrite).</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>")
other
(defxdoc rewrite-equiv
  :parents (rewrite)
  :short "Force ACL2 to perform substitution using a stylized @(see
 equivalence) hypothesis"
  :long "<p>@('Rewrite-equiv') is actually the @(see identity) function:
 @('(rewrite-equiv x) = x') for all @('x').  However, a term of the form
 @('(hide (rewrite-equiv (equiv x y)))') appearing in the hypothesis induces
 ACL2 to aggressively substitute @('y') for @('x') when @('equiv') is an @(see
 equivalence) relation (including @('equal')) and @('x') appears in a context
 in which @('equiv') is being maintained.</p>

 <p>Equivalence relations appearing in the hypothesis are not generally used by
 ACL2 to perform substitutions except under special circumstances, such as when
 one argument is a symbol or a constant or during the fertilization stage of
 the @(see waterfall) process. A stylized @('rewrite-equiv') expression of the
 form @('(hide (rewrite-equiv (equiv x y)))') can be used to override this
 default behavior.  Care should be taken in using @('rewrite-equiv'), however,
 because it can easily result in rewrite loops.</p>

 <p>For an example of a @(see clause-processor) that leverages
 @('Rewrite-equiv') to induce substitution using equivalence relations
 appearing in the hypothesis, see @(see rewrite-equiv-hint).</p>")
other
(defxdoc rewrite-if-avoid-swap
  :parents (rewrite system-attachments)
  :short "Control rewriter's swapping of branches of @('IF') calls"
  :long "<p>This topic concerns an advanced control for the ACL2 prover.</p>

 <p>By default, the ACL2 rewriter may swap true and false branches of a call of
 @('IF'), in particular when the test is a call of @('NOT').  Attach the
 function @('constant-t-function-arity-0') to defeat this behavior.  Attach the
 function @('constant-nil-function-arity-0') to restore the default
 behavior.</p>")
other
(defxdoc rewrite-lambda-modep
  :parents (rewrite)
  :short "switch controlling rewriting of lambda objects"
  :long "<p>@('Rewrite-lambda-modep') is an identity function with no purpose
  other than to serve as a switch controlling whether and how the ACL2 prover
  rewrites quoted @('lambda') objects in argument positions of @(see ilk)
  @(':FN').  Behavior is determined by the enabled status of two runes
  associated with @('rewrite-lambda-modep'), the executable-counterpart rune
  and the definition rune.  See @(see rewrite-lambda-object).</p>")
other
(defxdoc rewrite-lambda-object
  :parents (rewrite)
  :short "rewriting lambda objects in :FN slots"
  :long "<p>@(tsee Lambda) objects are quoted constants passed to @(see scion)s
  and applied as functions by @(tsee apply$).  The ACL2 rewriter can be made to
  replace the bodies of quoted @('lambda') objects with (supposedly) simpler
  bodies that are @(tsee ev$) equivalent, when the lambda objects occur in
  slots of @(see ilk) @(':FN').  However, there are restrictions on which
  lambda objects can be so simplified, restrictions on the techniques available
  to the rewriter during the simplification of @('lambda') bodies, and
  restrictions controlling whether the simplified body replaces the original or
  is ignored.  We explain below.</p>

  <h3>When an Occurrence of a @('lambda') Objects Is Eligible</h3>

  <p>An occurrence of a quoted @('lambda') object is eligible to be simplified
  provided</p>

  <ul>
  <li>(a) it occurs in a @(':FN') position of a call of a @(see scion),</li>

  <li>(b) the @('lambda') object is well-formed (see @(tsee
  well-formed-lambda-objectp)),</li>

  <li>(c) every function symbol mentioned in the body has been warranted</li>

  </ul>

  <p>However, eligible quoted @('lambda') objects are not modified at all if
  the @(see rune) @('(:executable-counterpart rewrite-lambda-modep)') is @(see
  disable)d.  That rune is enabled by default.</p>

  <p>Condition (b) implies the body of the @('lambda') is in fact a well-formed
  ACL2 term (so the rewriter can explore it), every function symbol in it is
  @(see badge)d (so that function objects mentioned are used properly), that
  every variable symbol occurring freely in the body is among the formals of
  the @('lambda') object, and together with (c) implies that the term
  ``behaves'' as expected if the appropriate warrant hypotheses govern this
  occurrence of the object.  This last implication means that @(tsee ev$) of
  the body is equal to unquoted body (under a suitable assignment), which means
  we can replace the unquoted body.</p>

  <p>If (a) holds but either (b) or (c) fails, then a
  @('"rewrite-lambda-object"') warning message is printed during the proof.
  However, this message is only printed once per @('lambda') object per proof
  attempt because otherwise the presence of ill-formed @('lambda')-like objects
  in a conjecture will litter the output with repeated warnings.  You may turn
  these warnings off with @('(')@(tsee toggle-inhibit-warning)
  @('"Rewrite-lambda-object")').</p>

  <h3>Restrictions During Rewriting of a @('Lambda') Body</h3>

  <p>The rewriter is restricted in three ways when rewriting the bodies of
  eligible occurrences of @('lambda') objects.</p>

  <p>First, the user can specify one of two actions the rewriter can take on an
  eligible @('lambda') object occurrence (in addition to taking no action as
  controlled by the @('rewrite-lambda-modep') rune mentioned above).  The
  available actions are to recursively call the rewriter and normalize the
  result, or to do syntactic cleaning only.  The default is recursive
  rewriting, with the restrictions explained in below.  Syntactic cleaning just
  eliminates declarations, guards, and various tags irrelevant to the logical
  value of the body.  We describe how the user specifies the action to be used
  in @(see rewrite-lambda-object-actions).  We give more details about these
  two kinds of @('lambda') body simplification in @(see
  rewriting-versus-cleaning-up-lambda-objects).</p>

  <p>Second, warrant hypotheses in the goal @(see clause) are the only
  contextual information ``imported'' from the goal clause and made available
  while rewriting a @('lambda') body.  That means type information about
  variables and other terms is forgotten, as are any linear arithmetic
  relationships.  The reason is simple: the variables in the body are in a
  different scope than the variables outside the @('lambda') object.  Put
  another way, we do not know, in general, to what the @('lambda') object will
  eventually be applied and so, in ACL2's untyped logic, we know nothing about
  its formal variables.

  (Actually, we not only ``import'' the warrants from the goal clause, we
  import every ground hypothesis governing the @('lambda') object's occurrence.
  But practically speaking that means we only import warrant hypotheses.  A
  more sophisticated handling of contextual information can be imagined.  For
  example, if the @('lambda') object occurs as the first argument of a @(tsee
  loop$) scion, like @('collect$') or @('sum$'), then the rewriter could
  perhaps extract type information from the target and import that information.
  For example, perhaps every element of the target is a number.  In that case,
  since we know the @('lambda') object in a @('loop$') scion call is only
  applied to elements of that list, we would then be allowed to assume the
  corresponding formal of the @('lambda') object is a number.  But that more
  sophisticated handling of contextual information has not been
  implemented.)</p>

  <p>Third, recursive functions are never opened when rewriting @('lambda')
  bodies.  For example, if @('(len (cons e x))') occurs in a @('lambda') body,
  you might expect it to be simplified to @('(+ 1 (len x))'), because that is
  what generally happens to that term when occurrences outside @('lambda')
  objects are rewritten.  ACL2 normally controls the expansion of recursive
  functions by reference to terms that already occur within the current goal.
  But the @('lambda') object effectively shares no variables with the
  surrounding goal and those heuristics are inapplicable.  Preliminary
  experiments with allowing expansions of recursive functions inside
  @('lambda') objects have produced unsatisfactory results such as runaway
  expansions.  So at the moment we allow no recursive expansions.</p>

  <p>The ACL2 implementors hope to address both of the above problems in
  eventual future releases.</p>

  <p>Syntactic cleaning, in contrast to the restricted rewriting just
  described, eliminates declarations, guards, and other compiler-related tags
  introduced by translation of @('lambda$') and @('loop$').  It does beta
  reduction, which eliminates local variable names (other than the formals of
  the @('lambda') object).  And it replaces the last argument of calls of
  @(tsee do$) by @('nil') if that argument is a quoted constant other
  than @('nil').  (This argument is irrelevant to the value of the
  @('do$') term and only used in error reporting.)</p>

  <h3>What Happens After Rewriting a @('Lambda') Body</h3>

  <p>After the specified action on the body, <i>b</i>, of
  @('(lambda(')<i>v1...vn</i>@(')')<i>b</i>@(')') to produce <i>b'</i> the
  decision must be made as to whether to return the @('lambda') with the
  rewritten body, @('(lambda(')<i>v1...vn</i>@(')')<i>b'</i>@(')'), or to
  ignore the rewrite and return the original (unrewritten) object.  ACL2
  ignores the rewrite and returns the original @('lambda') object if any of the
  following three cases obtains:</p>

  <ul>
  <li>(a) <i>b'</i> contains variables other than
  the @('lambda') formals <i>v1,...,vn</i>,</li>

  <li>(b) <i>b'</i> is not tame, or</li>

  <li>(c) some function symbol appearing in <i>b'</i> has no warrant
  hypothesis in the goal clause but forcing is disabled (see @(tsee force)).</li>
  </ul>

  <p>In all cases, the rewriter prints a @('"rewrite-lambda-object"') warning
  when the rewritten body is different from the original one but the rewrite is
  rejected.  The warning message displays the before and after @('lambda')
  objects, lists the rewrite rules used, and explains which of the three
  conditions above was violated.  However, this message is only printed once
  per @('lambda') object per proof attempt because otherwise the presence of a
  @('lambda') object that rewrites inappropriately will litter the output with
  repeated warnings.</p>

  <p>Condition (a) can arise if a rewrite rule introduces a free variable;
  disabling that rewrite rule is recommended.  Condition (b) can arise if some
  rewrite rule introduces a function symbol that has not been warranted;
  disabling that rule can often solve that problem but perhaps a better
  response is to use @(tsee defwarrant) to issue a warrant for the offending
  function symbol and then supply that warrant as a hypothesis to the goal; the
  latter response is perhaps better because it means all the ``usual''
  rewriting is done, normalizing terms as expected.  Condition (c) can be
  addressed by using @('defwarrant') to issue a warrant for the offending
  function symbol and enabling forcing (see @(tsee force)).</p>

  <p>The warning message noted above can become annoying.  You may turn these
  warnings off with @('(')@(tsee toggle-inhibit-warning)
  @('"Rewrite-lambda-object")').</p>

  <p>Be advised that if the @('"rewrite-lambda-object"') warning has been
  inhibited (by you or some book included in your session) and then, when
  looking at, say, the checkpoints in a failed proof, you see a @('lambda')
  object that you expected to be simplified but was not, you may think
  rewriting was not attempted for it, for some reason, when in fact it was
  attempted but rejected.  You can @('(toggle-inhibit-warning
  "Rewrite-lambda-object")') and replay the proof attempt to see (all) the
  rejected @('lambda') object rewrites.</p>

  <h3>A Possible Confusion</h3>

  <p>A metafunction that is included in the book @('projects/apply/top') can
  also cause quoted @('lambda') objects to be rewritten.  This metafunction,
  called @('relink-fancy-scion'), is called on certain calls of the fancy
  @('loop$') scions, e.g., calls of @(tsee always$+), @(tsee collect$+), @(tsee
  sum$+), etc.  The goal of that metafunction is to keep the list of ``global
  variables'' in some normal form.</p>

  <p>For example,consider the term</p>

  @({
  (collect$+ (quote
              (lambda (loop$-gvars loop$-ivars)
                (cons (car loop$-gvars)
                      (cons (car (cdr loop$-gvars))
                            (cons (car loop$-ivars) 'nil)))))
             (list a b)
             target)
  })

  <p>which is (essentially) the translation of @('(loop$ for e in target
  collect (list a b e))').  Suppose that in some case of a proof about this
  term the hypothesis @('(equal a b)') governs this term.  The term would thus
  become</p>

  @({
  (collect$+ (quote
              (lambda (loop$-gvars loop$-ivars)
                (cons (car loop$-gvars)
                      (cons (car (cdr loop$-gvars))
                            (cons (car loop$-ivars) 'nil)))))
             (list a a)
             target)
  })

  <p>@('Relink-fancy-scion') will rewrite that term to</p>

  @({
  (collect$+ (quote
              (lambda (loop$-gvars loop$-ivars)
                (cons (car loop$-gvars)
                      (cons (car loop$-gvars)
                            (cons (car loop$-ivars) 'nil)))))
             (list a)
             target)
  })

  <p>which eliminates the duplicate entry in the list of globals and, as a
  necessary side effect, also replaces the body of the lambda object to
  eliminate the term @('(car (cdr loop$-gvars))').</p>

  <p>The application of the metafunction @('relink-fancy-scion') can easily but
  mistakenly be attributed to the rewriting of @('lambda') objects but it is
  not!  The metafunction is applied to the whole @('collect$+') term (and calls
  of every other fancy scion), not just the @('lambda') object.</p>

  <p>If you want to avoid this normalization of the globals, disable the @(see
  rune) @('(:meta relink-fancy-scion-correct)').</p>")
other
(defxdoc rewrite-lambda-object-actions
  :parents (rewrite)
  :short "actions available when rewriting lambda objects"
  :long "<p>As explained in @(see rewrite-lambda-object) the rewriter can be
  applied to eligible occurrences of quoted @('lambda') objects.  That
  documentation also describes eligibility, what happens during, and what
  happens after the specified action, with a focus on recursively rewriting the
  @('lambda') body.  This topic discusses how to specify the desired
  action.</p>

  <p>The user can specify one of three actions by manipulating the enabled
  status of the @(see rune) @('(:executable-counterpart rewrite-lambda-modep)')
  and the enabled status of @('(:definition rewrite-lambda-modep)').  Recall
  that such runes can be abbreviated @('(:e rewrite-lambda-modep)') and @('(:d
  rewrite-lambda-modep)').  But in this discussion, we'll abbreviate them still
  further by <i>e</i> and <i>d</i>, respectively.</p>

  <p>The actions available on the body of an eligible @('lambda') object
  occurrence are</p>

  <ul>
  <li>rewrite:  <i>e</i> and <i>d</i> enabled</li>

  <li>syntactically clean: <i>e</i> enabled and <i>d</i> disabled</li>

  <li>hands-off (no action): <i>e</i> disabled</li>

  </ul>

  <p>Since the action is determined by the enabled status of runes, it can be
  specified by the user by appropriate global @(tsee in-theory) events or by
  goal-specific, local @(':in-theory') @(':')@(tsee hints).  There are three
  0-ary macros that expand into appropriate theories <i>provided</i> the only
  runes you wish to affect are our so-called <i>e</i> and <i>d</i>.</p>

  <p> The three macros are @(tsee rewrite-lambda-objects-theory), @(tsee
  syntactically-clean-lambda-objects-theory), and @(tsee
  hands-off-lambda-objects-theory), with the obvious meanings.  For example,
  @('(syntactically-clean-lambda-objects-theory)') macroexpands to</p>

  @({
  (e/d ((:executable-counterpart rewrite-lambda-modep))   ; enable ``e''
       ((:definition rewrite-lambda-modep)))              ; disable ``d''
  })

  <p>Since <i>e</i> and <i>d</i> are both initially enabled in ACL2, eligible
  @('lambda') objects are rewritten by default unless you change the status of
  <i>e</i> and/or <i>d</i>.</p>

  <p>For example, to make the prover just syntactically clean eligible
  @('lambda') objects in @('Subgoal 3') of some proof attempt you could provide
  the @(':hint')

   @({

  ("Subgoal 3"
    :in-theory (syntactically-clean-lambda-objects-theory))

  })</p>

  <p>Note however that if you also need to adjust the status of some other rune
  in that same hint you must create a theory expression that includes the
  appropriate use of <i>e</i> and <i>d</i>.  For example, to also enable
  @('LEMMA1') but disable @('LEMMA2') while specifying use of syntactic
  cleaning you could write:</p>

  @({
  ("Subgoal 3"
   :in-theory (e/d ((:executable-counterpart rewrite-lambda-modep)
                    LEMMA1)
                   ((:definition rewrite-lambda-modep)
                    LEMMA2)))
  })

  <p>For details on what syntactic cleaning is and why it is sometimes
  useful, see @(see rewriting-versus-cleaning-up-lambda-objects).</p>")
other
(defxdoc rewrite-lambda-objects-theory
  :parents (theories theory-functions rewrite)
  :short "how to specify rewriting of lambda objects"
  :long "<p>The enabled status of two @('rewrite-lambda-modep') runes are used
  as flags to determine the action taken when eligible @('lambda') objects are
  encountered by the ACL2 rewriter.  See @(see rewrite-lambda-object) and
  @(tsee rewrite-lambda-object-actions).  To make the rewriter dive into the
  body of an eligible @('lambda') object, both @('(:executable-counterpart
  rewrite-lambda-modep)') and @('(:definition rewrite-lambda-modep)') must be
  enabled in the then-current theory.  The 0-ary function
  @('rewrite-lambda-objects-theory') returns such a theory.</p>

  <p>In fact, diving into eligible quoted @('lambda') object constants to
  rewrite the body is the default action when ACL2 starts up.  See @(see
  rewriting-versus-cleaning-up-lambda-objects) for why you might want to change
  the default action when eligible @('lambda') objects are encountered by the
  rewriter.</p>

  <p>The expression @('(rewrite-lambda-objects-theory)') macroexpands to the
  theory expression</p>

  @({
  (e/d ((:executable-counterpart rewrite-lambda-modep)
        (:definition rewrite-lambda-modep))
       nil)
  })

  <p>which is a theory equal to the current theory except that the
  executable-counterpart rune and the definition rune of
  @('rewrite-lambda-modep') are enabled.  This expansion is suitable for use in
  an @(tsee in-theory) event or @(':in-theory') hint (see @(':')@(tsee
  hints)).</p>

  <p>Both these two runes are initially enabled, so eligible @('lambda') object
  bodies are rewritten by default until and unless some event (e.g., an @(tsee
  in-theory) or @(tsee include-book)) or a superior local subgoal hint changes
  the status of those runes.</p>

  <p>For example, if @('lambda') object rewriting has been disabled globally
  and you wish to enable it for @('Subgoal 3') of some proof, you could use
  the @(':')@(tsee hints)</p>

  @({
  ("Subgoal 3"
   :in-theory (rewrite-lambda-objects-theory))
  })

  <p>Note that if you also wish to enable or disable other runes in the same
  subgoal you must construct an appropriate theory.</p>

  <p>For example, if in @('Subgoal 3') of some proof you wanted to enable
  @('LEMMA1') and disable @('LEMMA2') in a theory that will also allow
  rewriting of @('lambda') objects, you might write</p>

  @({
  ("Subgoal 3"
   :in-theory (set-difference-theories
                 (union-theories (rewrite-lambda-objects-theory)
                                 '(LEMMA1))
                 '(LEMMA2)))
  })

  <p>Some users might prefer</p>

  @({
  ("Subgoal 3"
   :in-theory (e/d ((:executable-counterpart rewrite-lambda-modep)
                    (:definition rewrite-lambda-modep)
                    LEMMA1)
                   (LEMMA2)))
  })

  <p>See @(see theories) for general information about theories and how to
  create and use them.</p>")
other
(defxdoc rewrite-quoted-constant
  :parents (rule-classes)
  :short "Make a rule to rewrite a quoted constant"
  :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>Note: It is helpful to know some basic facts about the ACL2 rewriter; see
 @(see random-remarks-on-rewriting).</p>

  @({
  Example Forms:
  (defthm lambda-id
    (fn-equal '(lambda (x) x) 'identity)
    :rule-classes :rewrite-quoted-constant)

  (defthm set-normalizer
    (set-equalp (drop-duplicates-and-sort x) x)
    :rule-classes :rewrite-quoted-constant)

  (defthm lambda-id-generalized
    (implies (symbolp v)
             (fn-equal (list 'lambda (list v) v)
                       'identity))
    :rule-classes :rewrite-quoted-constant)
  })

  <p>To be accepted with rule-class @(':rewrite-quoted-constant') a conjecture
  must have one of the following three</p>
  @({
  General Forms:

  (IMPLIES hyps (equiv 'const1 'const2))        ; [1]

  (IMPLIES hyps (equiv (fn var) var))           ; [2]

  (IMPLIES hyps (equiv (constructor ...) rhs))  ; [3]
  })

  <p>where</p>
  <ul>

  <li>@('hyps') is a term (typically a conjunction) and may include @(tsee
  force) and @(tsee syntaxp) hypotheses with the usual semantics,</li>

  <li>@('equiv') is a known @(see equivalence) relation and, in the case of
  @('[1]') and @('[2]'), @('equiv') is not @('EQUAL'),</li>

  <li>@('var'), in form @('[2]'), is a variable symbol, and</li>

  <li> @('constructor'), in form @('[3]'), is an explicit value ``constructor''
  function symbol listed in @('*one-way-unify1-implicit-fns*').  The list just
  mentioned includes @('cons'), which can be used to match non-empty list
  constants, @('coerce'), which can match string constants,
  @('intern-in-package-of-symbol'), which can match symbol constants, and
  @('binary-+') and certain other arithmetic primitives which can match numeric
  constants.  See @(see random-remarks-on-rewriting) for some examples.</li>

  </ul>

  <p>If a rule meets the criteria for both a form @('[2]') rule and a form
  @('[3]') rule, then it is considered to be a form @('[2]') rule.</p>

  <p>The function, @('fn'), in a form @('[2]') rule is called the
  ``normalizer.''  We explain this terminology as we discuss how such rules are
  used.</p>

  <p>The @(':rewrite-quoted-constant') rule-class is permitted to specify a
  @(':corollary') and/or a @(':loop-stopper'), with the usual syntax and
  meaning.  See @(':')@(tsee rule-classes).  Note that for forms @('[1]') and
  @('[2]') above a @(':')@('loop-stopper') is probably irrelevant as the forms
  do not usually contain multiple variable symbols.</p>

  <p>Once a @(':rewrite-quoted-constant') rule is proved and stored, the
  rewriter behaves as follows.  When a quoted constant is encountered as the
  target term to be rewritten, the rewriter considers each enabled
  @(':rewrite-quoted-constant') rule (most-recent first), looking for those
  whose @('equiv') refines (see @(':')@(tsee refinement)) the equivalence
  relation being maintained by the rewriter for the given occurrence of the
  target.  The rewriter tries to apply each such rule in turn (as described
  below) and replaces the target by the rewritten result of the first
  applicable rule.</p>

  <p>A rule applies if the ``pattern'' (see below) in the conclusion
  ``matches'' the quoted constant and the @('hyps') can be relieved in the
  usual sense, including the treatment of free variables, pragmatic directives
  like @(tsee force) and @(tsee syntaxp), and heuristics such as those
  controlled by any @(':')@(tsee loop-stopper) options in the rule-class or
  @(':')@('restrict') @(see hints).  If these conditions are met, the quoted
  constant is replaced by the ``result.''  But the exact meanings of
  ``pattern,'' ``match'' and ``result'', here, are a little different from their
  meanings for ordinary @(':rewrite') rules and depend on which of the three
  forms is being applied.</p>

  <ul>

  <li>A form @('[1]') rule, whose conclusion is @('(equiv 'const1 'const2)'),
  has @(''const1') as its pattern and that pattern matches the target constant
  @(''const') only when @('const1') is exactly @('const').  The result is
  @(''const2').  Note that it is impossible to prove a form @('[1]') rule whose
  equivalence is @('equal') unless the two constants are identical, so we
  disallow that case.</li>

  <li>A form @('[2]') rule, whose conclusion is @('(equiv (fn var) var)'), is
  most easily understood by swapping the roles of left- and right-hand sides of
  its conclusion.  Its pattern is the right-hand side, @('var'), and its result
  is derived from the left-hand side, @('(fn var)').  The reason we use the
  form shown here is so that the same conjecture might also be used as an
  ordinary @(':rewrite') rule without forcing the user to type a
  @(':corollary') with the sides swapped.  Since form @('[2]') rules have a
  variable as the pattern they will match any quoted constant, @(''const'), by
  binding @('var') to @(''const').  The result is the quoted constant, if any,
  obtained by rewriting @('(fn var)') under that binding of @('var').  If that
  rewrite does not result in a constant, no replacement is made, i.e., it is as
  though the rule did not match.  Note that it is pointless to prove a form
  @('[2]') rule whose equivalence is @('equal') because it would replace a
  quoted constant by itself, so we disallow that equivalence.

  <br> </br>
  <br> </br>

  Intuitively, @('fn') is a function that normalizes every member of the
  @('equiv') equivalence class: given a constant that is a member of the class
  it returns its ``normal'' form.  That is why we call @('fn') the
  ``normalizer'' for @('equiv').  However, you do not have to prove anything
  like normality or canonicality; you just have to prove that @('fn') returns a
  member of the class.  Having several different normalizers is possible but it
  is best if only one is enabled at a time.

  <br> </br>
  <br> </br>

  When @('var') is bound to a constant, the rewriter will first try to reduce
  @('(fn var)') to a constant by simple evaluation.  If that fails, it tries
  using lemmas.  If the normalizer or one of its subfunctions is disabled or is
  non-executable or has a disabled executable counterpart the attempt to simply
  evaluate @('(fn var)') (under the assignment of @(''const') to @('var')) may
  fail.  That is why full-blown rewriting of @('(fn var)') is tried instead.
  It might happen that evaluation fails but lemmas produce a constant.

  <br> </br>
  <br> </br>

  <b>The fact that form @('[2]') rules are used ``backwards,'' with the roles
  of the left- and right-hand sides swapped, has some ramifications worth
  noting.</b> First, you can also classify the same formula as a @(':rewrite')
  rule (but of course as such it won't rewrite quoted constants); as a
  @(':rewrite') rule it rewrites instances of @('(fn var)') to the
  corresponding instance of @('var').  Second, when a
  @(':rewrite-quoted-constant') rule is added, the new rule is compared to old
  rules for subsumption and warning messages are generated; however form
  @('[2]') rules are omitted from this subsumption check because their patterns
  match every constant (in the equivalence class).  Third, if you inspect a
  form @('[2]') rule with @(tsee pr), it reports the actual syntax typed, e.g.,
  the ``@('Lhs')'' is @('(fn var)') and the ``@('Rhs')'' is @('var').  But, if
  you @(':')@(tsee monitor) a form @('[2]') rule and then interact with the
  resulting @(see break-rewrite) you will see that the @(tsee brr-commands)
  @(':lhs') and @(':rhs') report the swapped results.  That is, in the break,
  @(':lhs') will be @('var') and @(':rhs') will be @('(fn var)').  This is
  different from the display by @('pr') because @('pr') reports the actual
  syntax but interactive breaks report how the rule is being used.  We think
  the interactive user, out of long habit, will type @(':lhs') to see the
  pattern being matched and we did not think it wise to add a special command
  just to see the pattern in a form @('[2]') rule.  Fourth, if a form @('[2]')
  rule is mentioned in the report by @(tsee pl) the ``New term'' is reported to
  be @('(fn 'const)'), however replacement of @(''const') occurs only if @('(fn
  'const)') reduces to a quoted constant by rewriting.</li>

  <li>A form @('[3]') rule, whose conclusion is @('(equiv (constructor ...)
  rhs)'), matches the constant @(''const') provided @(''const') is an instance
  of @('(constructor ...)') under some variable substitution @('s').  We
  illustrate cases where quoted constants are instances of ``constructor''
  terms below and in @(see random-remarks-on-rewriting).  Note that form
  @('[3]') rules allow the equivalence relation to be @('equal').  Use of
  @('equal') here could cause looping rewrites if the @('rhs') reduces to a
  constant.  But we allow it because, as noted below, such a rule will also
  permit you to rewrite a quoted constant into an equivalent term that is not a
  quoted constant.</li>

  </ul>

  <p>It is important to realize that form @('[1]') and form @('[3]') rules only
  apply to the top-level of a quoted constant.  We discuss this at length
  because it can cause some confusion.  The examples below are drawn from the
  community book @('books/demos/rewrite-quoted-constant-examples').  That book
  introduces @('set-equalp') as an equivalence relation and proves various
  @(':rewrite-quoted-constant') rules to rearrange the quoted constants
  occurring in @('set-equalp') contexts.  Assume all the quoted constants
  mentioned below occur in @('set-equalp') contexts.</p>

  <p>The form @('[1]') rule @('(set-equalp 77 nil)') will not cause @(''(1 2 3
  . 77)') to rewrite to @(''(1 2 3)').  Because ACL2 applications frequently
  involve huge quoted list constants, we believe that making the rewriter
  explore them down to the tips would be prohibitively expensive.</p>

  <p>However, form @('[2]') rules, of the general form @('(implies
  hyps (equiv (fn var) var))'), allow the normalizer to be applied to every
  quoted constant occurring in a suitable @('equiv') context.  The normalizer
  can then do a root-and-branch exploration of the constant to compute its
  replacement.</p>

  <p>For example, the @('rewrite-quoted-constants-examples') book cited above
  defines the normalizer @('(drop-dups-and-sort var)') to coerce its argument
  to a @(tsee true-listp), eliminate duplicate elements, and sort the remaining
  elements.  It then proves the form @('[2]') rule
  @('(set-equalp (drop-dups-and-sort var) var)').  Now consider how this rule
  is used when the rewriter encounters @(''(3 1 1 2 . 77)') in a
  @('set-equalp') context.  First, @('var') is bound to @(''const').  Then, the
  rewriter tries to relieve the instantiated hypotheses of the rule, if any.
  The example rule here has no hypotheses.  But you can provide some and
  perhaps use them to prevent calling the normalizer on this particular
  constant.  Since @('var') is bound to the constant @(''const') such
  hypotheses can usually just be computed.  Supposing the hypotheses are
  relieved, the rewriter then rewrites @('(drop-dups-and-sort 'const)').  Under
  the most common circumstance, this just causes your normalizer function, here
  @('drop-dups-and-sort'), to execute on the given constant.  (If you have
  verified the guard of the normalizer and @(''const') satisfies the guard,
  then the execution is in the underlying raw Common Lisp.)  In the most common
  circumstance, the function will return an explicit constant.  If that
  returned value is indeed a constant (and different from @(''const')), the
  rewriter replaces this occurrence of @(''const') by the returned value.
  Otherwise the rule does not apply.</p>

  <p>As noted earlier, form @('[3]') rules are only applied at the top-level of
  a quoted constant.  For example, the rule @('(set-equalp (cons x y) (my-cons
  x y))') will not cause @(''(1 2 3)') to rewrite to @('(my-cons 1 (my-cons
  2 (my-cons 3 nil)))') in @('set-equalp') contexts.  Instead, it would produce
  @('(my-cons 1 '(2 3))').</p>

  <p>But since the rewriter will eventually be called on that term, and since
  that term contains another top-level quoted constant, namely @(''(2 3)'), you
  might expect the rule to eventually be used to replace @(''(2 3)') by
  @('(my-cons 2 '(3))').  Indeed, that is what happens -- if you have proved
  that @('set-equalp') is a @(see congruence) for the second argument of
  @('my-cons'), maintaining @('set-equalp').  However, for technical reasons
  explained in comments in the book @('rewrite-quoted-constant-examples'), each
  rewrite occurs in a separate simplification step.  So turning @(''(1 2 3)')
  into @('(my-cons 1 (my-cons 2 (my-cons 3 nil)))') requires three
  simplification steps.  If the rule in question were @('(set-equalp (cons x
  y) (cons x (double-rewrite y)))') it would happen in one simplification step.
  See @('double-rewrite') and the examples in the book
  @('rewrite-quoted-constant-examples').</p>")
other
(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>")
other
(defxdoc rewriting-calls-of-apply$-ev$-and-loop$-scions
  :parents (apply$)
  :short "How the rewriter handles @('apply$'), @('ev$'), and @('loop$') terms"
  :long "<p>This section focuses on how ACL2 rewrites calls of @('apply$'),
  @('ev$'), and @('loop$') scions.  Our purpose is to explain the various ways
  the user can control that rewriting.  We do so by taking you through a
  particularly simple example, starting with a @('loop$') expression.</p>

  <p>We assume that the standard @('apply$') book has been included,</p>

  @({
  (include-book "projects/apply/top" :dir :system).
  })

  <p>and we suppose the function @('sq'), of one argument, has been defined
  and warranted (see @(tsee defwarrant).</p>

  <p>Recall that each @(tsee loop$) statement is translated
  into a call of some @('loop$') @(see scion) involving @('lambda') objects formed
  from the iterated expressions in the @('loop$') statement.  Thus, for example,</p>

  @({
  (loop$ for x in (cons a (cdr (cons x b))) collect (* (sq x) 3))
  })

  <p>is essentially translated into</p>

  @({
  (COLLECT$ '(LAMBDA (LOOP$-IVAR)
                     (BINARY-* (SQ LOOP$-IVAR) '3))
             (CONS A (CDR (CONS X B)))).
  })

  <p>Recall that you can view the cleaned up translation with @(':')@(tsee tc),
  and the discussion at @(tsee tc) explains what we mean by &ldquo;cleaned
  up&rdquo; here.</p>

  <p>So @('loop$') statements just introduce @('lambda') objects and scions
  into any conjecture using @('loop$').  These are rewritten like any other
  term in ACL2: the arguments are rewritten recursively and then enabled
  @(':')@(tsee rewrite) rules (including the definition of the scion) are
  tried.  Recall that ACL2 can rewrite @('lambda') constants. (See @(see
  rewrite-lambda-object) for when that can occur and how to control it.)</p>

  <p>So now consider what happens when the rewriter encounters the translation
  of the @('loop$') above.</p>

  @({
  (collect$ '(lambda (x) (binary-* (sq x) '3))  ; note where 3 occurs
            (cons a (cdr (cons x b)))
  })

  <p>it will rewrite the @('lambda') object and the @('cons') term, effectively
  turning the @('collect$') term into</p>

  @({
  (collect$ '(lambda (x) (binary-* '3 (sq x)))  ; note where 3 occurs now
            (cons a b))
  })

  <p>Then, if other rewrite rules about @('collect$') don't rewrite that, the
  the definition of @('collect$') will be tentatively tried.  By that we mean
  the body of the definition of @('collect$') is rewritten (in an environment
  binding locals to actuals) and then the rewriter decides heuristically
  whether to use the original call (with its rewritten arguments) or the
  rewritten body.  We do not discuss those heuristics here because they're the
  same for @('loop$') scions as for all other recursive functions in ACL2.</p>

  <p>The logical definition of @('collect$') is</p>

  @({
  (defun collect$ (fn lst)
    (if (endp lst)
        nil
        (cons (apply$ fn (list (car lst)))
              (collect$ fn (cdr lst))))).
  })

  <p>And in this case, the body will be tentatively rewritten in the
  environment where the locals @('fn') and @('lst') are bound as follows.</p>

  @({
  fn:  '(lambda (x) (binary-* '3 (sq x)))
  lst: (cons a b).
  })

  <p>As the rewriter descends through the body of @('collect$') it eventually
  encounters the @('apply$') term.  After rewriting its arguments, the
  @('apply$') term effectively becomes</p>

  @({
  (apply$ '(lambda (x) (binary-* 3 '(sq x)))
          (cons a 'nil))
  })

  <p>and then rules about @('apply$') are tried.</p>

  <p>Unless you disable it, the rule @('beta-reduction'), from the standard @('apply$') book above, will fire,
  transforming the above @('apply$') term to</p>

  @({
  (ev$ '(binary-* '3 (sq x))
       (cons (cons 'x a) 'nil)).
  })

  <p>(@('Beta-reduction') is enabled by default.  If you disable it, the
  @('apply$') term will not change unless you enable @('(:definition apply$)'),
  which is disabled by default.)</p>

  <p>But we recommend leaving @('beta-reduction') enabled and thus converting
  every @('apply$') of a @('lambda') object into an @('ev$') term.  There is a
  special feature of the rewriter for simplifying certain @('ev$') terms.  It
  is based on the fact that that (roughly speaking) the @('ev$') of a quoted
  tame term under an alist is the unquoted term with the alist applied as a
  substitution.  That is, the @('ev$') term above is equal to @('(binary-*
  '3 (sq a))').</p>

  <p>More precisely, if a <i>x</i> is a @(see tame) term and every
  non-primitive function symbol in <i>x</i> has been warranted (see @(tsee
  defwarrant)) and <i>a</i> is a @('cons') nest term representing a
  substitution <i>sigma</i> pairing the variable symbols occurring freely in
  <i>x</i> with terms, then @('(ev$ '')<i>x&nbsp;&nbsp;a</i>@(')') is equal to
  <i>x</i>/<i>sigma</i>, provided the warrants of all the non-primitive
  function symbols in <i>x</i> are assumed.</p>

  <p>This is implemented in the rewriter so that when an @('(ev$ 'x a)') is
  encountered and the following conditions hold</p>

  <ul>
  <li>the standard @('apply$') book has been included,</li>

  <li>the rune @('(:rewrite ev$-opener)') is enabled</li>

  <li>@('x') is a tame term</li>

  <li>all non-primitive function symbols in @('x') have been warranted (whether
  the warrants are assumed or not), and</li>

  <li>@('a') is a @('cons') term representing an alist on variables,</li>

  </ul>

  <p>then the following three actions are taken,</p>

  <ul>

  <li>The @('cons') term @('a') is converted to a substitution, @('sigma'), and
  that substitution is extended to a substitution, @('sigma''), by pairing with
  @('nil') each variable of @('x') that is unbound in @('sigma').  It should be
  observed that an unbound variable is assigned the value @('nil') by the
  definitions of @('ev$') (actually, of @('assoc')).</li>

  <li>The warrant for each non-primitive function in @('x') is @(see force)d if
  possible unless the warrant is already assumed in the current context.</li>

  <li>The @('(ev$ x a)') term is rewritten to the result of recursively
  rewriting @('x') under the substitution @('sigma'').</li>

  </ul>

  <p>Note that this eliminates @('ev$').</p>

  <p>If you see an @('ev$') of a quoted term in a checkpoint produced by the
  prover, you will know that one of the conditions above is not satisfied or
  that a necessary warrant could not be forced because forcing was disallowed
  or the warrant was assumed false in the context.</p>

  <p>If you would rather @('ev$') did not just disappear like this, disable
  @('(:rewrite ev$-opener)').  This might be desirable if the expansion
  produces a lot of cases and you can prove the theorem without exposing them.</p>

  <p>Sometimes you may wish for @('ev$') to expand, but to do so step-by-step,
  gradually working its way down through @('x'). Such behavior can be achieved
  by disabling @('ev$-opener') but enabling @('(:definition ev$)'), which is
  disabled by default.  However, the tentative application of the mutually
  recursive definitions of @('ev$') and @('apply$') can be quite slow when
  dealing with moderately large @('lambda') objects.  Step-by-step expansion of
  @('ev$') can be accomplished by the alternative but generally faster method
  of disabling @('(:rewrite ev$-opener)'), leaving @('(:definition ev$)')
  disabled, but proving your own version of @('ev$-opener') under a different
  name.</p>

  @({
  (defthm my-version-of-ev$-opener
    (and (implies (symbolp x)
                  (equal (ev$ x a) (cdr (assoc x a))))
         (equal (ev$ (list 'quote obj) a) obj)
         (implies (suitably-tamep-listp 3 nil args)
                  (equal (ev$ (cons 'if args) a)
                         (if (ev$ (car args) a)
                             (ev$ (cadr args) a)
                             (ev$ (caddr args) a))))
         (implies (and (not (eq fn 'quote))
                       (not (eq fn 'if))
                       (tamep (cons fn args)))
                  (equal (ev$ (cons fn args) a)
                         (apply$ fn (ev$-list args a)))))
    :hints (("Goal" :use ev$-opener))).
  })

  <p>By having the @('apply$') book's @('ev$-opener') disabled you shut off the
  special feature described above, and by having your own version of
  @('ev$-opener') enabled you push the @('ev$') through the quoted term with
  rewrite rules.  This can sometimes help narrow down which of the conditions
  above is unsatisfied, especially if you modify your version of the rule so
  that the @('tamep') and @('suitably-tamep-listp') hypotheses are @(tsee
  force)d.</p>")
other
(defxdoc rewriting-versus-cleaning-up-lambda-objects
  :parents (rewrite)
  :short "why change the default action on rewriting @('lambda') objects"
  :long "<p>See @(see rewrite-lambda-object) and @(tsee
  rewrite-lambda-object-actions) for background information on how the ACL2
  rewriter behaves on certain quoted @('lambda') objects.  In this topic we
  discuss why you might want to change that behavior.</p>

  <p>There are three basic actions the rewriter might take when it encounters
  a suitable @('lambda') object.</p>

  <ul>

  <li>recursively rewrite the body to get a new body,<br></br> by rewriting in
  the theory described in @(tsee rewrite-lambda-objects-theory) </li>

  <li>just clean it up syntactically,<br></br> by rewriting in the theory
  described by @(tsee syntactically-clean-lambda-objects-theory), or</li>

  <li>do nothing &mdash; leave @('lambda') object constants untouched.<br></br>
  by rewriting in the theory described by @(tsee
  hands-off-lambda-objects-theory).</li>

  </ul>

  <p>The reason we have several options has to do with the representation of
  @('lambda') objects as quoted constants in ACL2's first order logic.  Distinct
  @('lambda') objects are unequal and yet sometimes by rewriting their bodies
  to functionally equivalent terms under @(tsee ev$) they can become identical.</p>

  <p>For example, @(''(lambda (x) (+ 1 x))') and @(''(lambda (x) (+ x 1))') are
  unequal list constants.  But they are functionally equal and by rewriting
  their bodies we can make them identical.</p>

  <p>The problem is greatly magnified by the way @('lambda$') and @('loop$')
  expressions macroexpand into formal terms.  Their expansions are complicated
  with guards and tags that play key roles in their Common Lisp compilation and
  execution efficiency within the ACL2 top-level read-eval-print loop.  But
  those guards and tags are irrelevant to their logical meanings.  By
  eliminating the guards and tags from quoted @('lambda') objects in slots of
  @(tsee ilk) @(':FN') we increase the chances that different objects become
  identical.</p>

  <p>Consider the translation of a @('thereis') @('loop$') statement.  The
  @('thereis') @('loop$') operand looks for an element of the range that
  satisfies a given predicate and returns the first non-@('nil') value of that
  predicate.  The predicate is formally a @('lambda') object.  Below we
  translate a @('thereis') @('loop$') and show the result.</p>

  @({
  ACL2 !>:trans (loop$ for x on a
                       thereis
                       (if (equal (car x) b) x nil))

  (RETURN-LAST
   'PROGN
   '(LOOP$ FOR X ON A
           THEREIS
           (IF (EQUAL (CAR X) B) X NIL))
   (THEREIS$+
    '(LAMBDA
      (LOOP$-GVARS LOOP$-IVARS)
      (DECLARE (XARGS :GUARD (IF (TRUE-LISTP LOOP$-GVARS)
                                 (IF (EQUAL (LEN LOOP$-GVARS) '1)
                                     (IF (TRUE-LISTP LOOP$-IVARS)
                                         (EQUAL (LEN LOOP$-IVARS) '1)
                                         'NIL)
                                     'NIL)
                                 'NIL)
                      :SPLIT-TYPES T)
               (IGNORABLE LOOP$-GVARS LOOP$-IVARS))
      (RETURN-LAST
           'PROGN
           '(LAMBDA$ (LOOP$-GVARS LOOP$-IVARS)
                     (DECLARE (XARGS :GUARD (AND (TRUE-LISTP LOOP$-GVARS)
                                                 (EQUAL (LEN LOOP$-GVARS) 1)
                                                 (TRUE-LISTP LOOP$-IVARS)
                                                 (EQUAL (LEN LOOP$-IVARS) 1))))
                     (LET ((B (CAR LOOP$-GVARS))
                           (X (CAR LOOP$-IVARS)))
                          (DECLARE (IGNORABLE E X))
                          (IF (EQUAL (CAR X) B) X NIL)))
           ((LAMBDA (B X)
                    (IF (EQUAL (CAR X) B) X 'NIL))
            (CAR LOOP$-GVARS)
            (CAR LOOP$-IVARS))))
    (CONS B 'NIL)
    (LOOP$-AS (CONS (TAILS A) 'NIL))))

  => *
  })

  <p>The predicate being mapped is the quoted @('lambda') object in the first
  argument of the @('thereis$+').  When shorn of the logically irrelevant
  @('DECLARE') and @('RETURN-LAST') forms this particular quoted @('lambda')
  object becomes</p>

  @({
  '(LAMBDA
    (LOOP$-GVARS LOOP$-IVARS)
    ((LAMBDA (B X)
             (IF (EQUAL (CAR X) B) X 'NIL))
     (CAR LOOP$-GVARS)
     (CAR LOOP$-IVARS)))
  })

  <p>But now consider the closely related @('thereis') @('loop$') which is like
  the one translated above but uses different names for the variables.</p>

  @({
  (loop$ for y on aaa
         thereis
         (if (equal (car y) bbb) y nil))
  })

  <p>The @('lambda') object representing the predicate in this @('loop$'), when
  shorn of logically irrelevant material, is</p>

  @({
  '(LAMBDA
    (LOOP$-GVARS LOOP$-IVARS)
    ((LAMBDA (BBB Y)
             (IF (EQUAL (CAR Y) BBB) Y 'NIL))
     (CAR LOOP$-GVARS)
     (CAR LOOP$-IVARS)))
  })

  <p>But note that this @('lambda') object contains the ``variables'' @('BBB')
  and @('Y') where the earlier one contained @('B') and @('X').  However, they
  are not really variables!  They are symbol constants because they occur in
  quoted list constants.  Thus, the @('lambda') object generated for the first
  @('thereis') @('loop$') is different from the @('lambda') object generated
  from the &ldquo;closely related&rdquo; one.  They are just two different list
  constants.</p>

  <p>Thus, the translations of those two @('thereis') @('loop$')s are not
  instances of one another.  So if you proved a rewrite rule about the
  @('(loop$ for x on ...B...)')  and then the rewriter encountered @('(loop$ for y
  on ...BBB...)') the rule would not match.  (By the way, this problem has nothing
  special to do with @('thereis') @('loop$')s.  It happens on every kind of
  @('loop$') because the problem has everything to do with representing
  @('lambda') expressions as list constants.)</p>

  <p>Fortunately, it is sound to replace the body of a @('lambda') object with
  one that is equivalent under @(tsee ev$).  That can be done either by
  rewriting the body or by syntactically cleaning the body.  It turns out that
  both rewriting and syntactic cleaning produce the same result in this case
  and reduce these two distinct @('lambda') objects to this one.</p>


  @({
  '(LAMBDA
    (LOOP$-GVARS LOOP$-IVARS)
    (IF (EQUAL (CAR (CAR LOOP$-IVARS))
               (CAR LOOP$-GVARS))
        (CAR LOOP$-IVARS)
        'NIL))
  })

  <p>Actually, all that is needed in this case is the beta reduction of the
  two bodies.</p>

  <p>Syntactic cleaning eliminates declarations, guards, and other
  compiler-related tags introduced by translation of @('lambda$') and
  @('loop$').  It does beta reduction, which eliminates local variable
  names (other than the formals of the @('lambda') object).  And it replaces
  the last argument of calls of @(tsee do$) by @('nil') if that
  argument is a quoted constant other than @('nil').  (That argument is
  irrelevant to the value of the @('do$') term and only used in error
  reporting.)  The logical semantics of @('loop$') is best understood not by
  looking at its translation as we did above but by looking at the result of
  syntactically cleaning its translation.  That is done by the command
  @(':')@(tsee tc).  @('Tc') translates its argument, in this case the
  @('loop$') statement we've been studying, obtaining the large form shown
  above, and then syntactically cleans it, returning the internal
  representation of the logical semantics. </p>

  @({
  ACL2 !>:tc (loop$ for x on a
                    thereis
                    (if (equal (car x) b) x nil))
  (THEREIS$+ '(LAMBDA
               (LOOP$-GVARS LOOP$-IVARS)
               (IF (EQUAL (CAR (CAR LOOP$-IVARS))
                          (CAR LOOP$-GVARS))
                   (CAR LOOP$-IVARS)
                   'NIL))
             (CONS B 'NIL)
             (LOOP$-AS (CONS (TAILS A) 'NIL)))
  })

  <p>Note that the free variables of the term are @('A') and @('B').  The
  iteration variable, @('x') of the @('loop$') does not appear.  Instances of
  this term are formed by choosing instantiations of @('A') and @('B').</p>

  <p>(Note: The related command @(':')@(tsee tcp) translates, cleans, and then
  converts the internal form of the term into the &ldquo;pretty&rdquo;
  user-level syntax.  E.g., it converts the quoted @('LAMBDA') constant above
  to a @('lambda$') expression, converts the @('IF') expression to an @('AND'),
  and converts the @('CONS') terms into @('LIST') terms.  But for this
  discussion it is really better to see the internal form.  That @('LAMBDA')
  object above is really a list constant!)</p>

  <p><b>Before a newly proved @(':')@(tsee rewrite) or @(':')@(tsee linear)
  rule is stored, the conclusion is syntactically cleaned.</b></p>

  <p>Like syntactic cleaning, rewriting eliminates declarations, guards, and
  other compiler-related tags and does beta reduction &mdash; but these
  transformations are generally carried out by rules whose enabled status can
  be altered.  Furthermore, rewriting applies @(':rewrite') and other rules
  which might commute terms, open function definitions, etc.  We don't rewrite
  the conclusions of newly proved rules simply because the enabled rules may
  change from one event (or subgoal) to another.</p>

  <p>As noted earlier, there are three basic actions the rewriter might take
  when it encounters a suitable @('lambda') object.</p>

  <ul>
  <li>recursively rewrite the body to get a new body,</li>

  <li>just clean it up syntactically, or</li>

  <li>do nothing &mdash; leave @('lambda') object constants untouched.</li>

  </ul>

  <p>Since rules are cleaned before storage, it is almost always the case that
  you will want the prover either to rewrite @('lambda') objects or
  syntactically clean them.  In simple cases, like a rule about the first
  @('thereis') @('loop$') above and a conjecture about the @('second'), either
  action by the prover reduces &ldquo;closely related&rdquo; @('lambda')
  objects to identical objects, making it more likely that rules will fire.</p>

  <p>So which of the three actions do you want the rewriter to take when it
  encounters an eligible @('lambda') object?</p>

  <ul>

  <li>rewrite the body &mdash; best if there are multiple @('lambda') objects
  in the conjecture that need to be written to be identified, and in simple
  cases rewriting is equivalent to syntactic cleaning</li>

  <li>syntactic cleaning &mdash; best if you want the @('lambda') objects in
  the conjecture to match @(':rewrite') or @(':linear') rules containing
  closely related @('lambda') objects, but you find that otherwise necessary
  @(':rewrite') rules cause the rewriter to &ldquo;overshoot&rdquo; the
  syntactically cleaned term as illustrated further below</li>

  <li>hands off &mdash; fairly unuseful since rules are cleaned up before
  storage.  However, one use of this is if you prove a lemma containing a
  @('lambda') object but store it with @(':rule-classes nil') and then
  @(':use') an instance of it in the @(':hints') for some conjecture that
  involves the very same @('lambda') objects.</li>

  </ul>

  <p>We now illustrate some typical problems that arise when proving theorems
  about @('loop$')s.  These examples are documented in the book
  @('books/projects/apply/rewriting-versus-cleaning-examples').</p>

  <p><b>Why you might want to use syntactic cleaning:</b> Suppose you prove the
  @(':rewrite') rule below.  It says that a certain @('thereis') @('loop$')
  computes the same answer as the function @(tsee last).</p>

  @({
  (defthm loop$-can-be-last
    (implies (listp a)
             (equal (loop$ for x on a
                           thereis
                           (if (atom (cdr x)) x nil))
                    (last a))))
  })

  <p>What term does this rule target?  We can answer that by using the
  @(':')@(tsee tc) command.</p>

  @({
  ACL2 !>:tc (loop$ for x on a
                    thereis
                    (if (atom (cdr x)) x nil))
   (THEREIS$ '(LAMBDA (LOOP$-IVAR)
                      (IF (ATOM (CDR LOOP$-IVAR))
                          LOOP$-IVAR 'NIL))
             (TAILS A))
  })

  <p>By the way, a more common way to see the rules created by an event is to
  use the @(':')@(tsee pr) command.  But that command displays the terms of the
  rule in user-level syntax and we want to see the internal form here.  The
  &ldquo;@('lambda') expression&rdquo; is really a quoted constant.</p>

  <p>Now imagine you are proving a conjecture that involves that identical (!)
  @('loop$').  Of course, translation will replace the @('loop$') by a rather
  large tagged term containing compiler directives, etc.  Shorn of that
  material the term would become the @('thereis$') term above, but the
  translation is what is in the initial @('Goal').  Imagine further that you're
  doing this proof in a theory that allows the rewriter to recursively rewrite
  the bodies of quoted @('lambda') objects, i.e., you are in a theory as
  described by @(tsee rewrite-lambda-objects-theory).  ACL2 starts up in such a
  theory and unless you've changed the enabled status of the
  @('rewrite-lambda-modep') runes rewriting @('lambda') objects is the default
  behavior.</p>

  <p>You might expect the @('loop$-can-be-last') rule to fire and replace the
  @('thereis$') term in the @('Goal') by @('(last a)').  But that will not
  happen!  The rule won't fire!</p>

  <p>The reason is that before the rewriter rewrites the @('thereis$') term it
  rewrites its arguments.  The quoted @('lambda') object in the Goal is
  rewritten first.  That is necessary because the translated @('loop$')
  contains tags, etc.  But the rewriter does more than just clean up the body.
  It &ldquo;overshoots&rdquo; and opens the nonrecursive function @('atom') and
  swaps the branches of the @('if') to eliminate the @('not') thus introduced.
  The quoted @('lambda') object becomes</p>

  @({
  '(LAMBDA (LOOP$-IVAR)
           (IF (CONSP (CDR LOOP$-IVAR))
               'NIL
               LOOP$-IVAR))
  })

  <p>So when the rewriter then tries to rewrite the @('thereis$') terms the
  quoted @('lambda') object in the rule does not match the one in the rewritten
  @('Goal').</p>

  <p>If the rewritten goal is printed, as it is likely to be a checkpoint, you
  will see the rewritten body with the @('consp') instead of @('atom') in it.
  As usual, pay attention to the checkpoints.</p>

  <p>One way to respond to this problem would be to &ldquo;hobble&rdquo; the rewriter
  by shifting over to syntactic cleaning of quoted @('lambda') objects.  This could
  be done by providing a local subgoal hint in which you specify</p>

  @({
  :in-theory (syntactically-clean-lambda-objects-theory)
  })

  <p>which would prevent the rewriter from diving into the bodies of
  @('lambda') objects and just clean them instead.</p>

  <p><b>Why you should probably use rewriting:</b> There is a deeper lesson
  here than just that you might want to hobble the rewriter to prevent it from
  diving into quoted @('lambda') bodies.  In our view the actual problem is
  with the @('loop$-can-be-last') rule itself.  ACL2 users are taught to
  express rules in maximally rewritten terms.  No experienced user would pose a
  rule with a non-recursive function like @('atom') in its lefthand side.  The
  best response to this situation, which may or may not be practical depending
  on how @('loop$-can-be-last') came to be a rule in the session, is to change
  that rule to</p>

  @({
  (defthm loop$-can-be-last
    (implies (listp a)
             (equal (loop$ for x on a
                           thereis
                           (if (consp (cdr x)) nil x))
                    (last a))))
  })

  <p>This version of the rule would not only rewrite the @('thereis') @('loop$') above
  but rewrites</p>

  @({
  (loop$ for x on a
         thereis
         (if (atom (cdr x)) x nil))
  })

  <p>because, as illustrated above, the rewriter by default dives into the
  translated @('loop$') and &ldquo;normalizes&rdquo; the resulting
  @('thereis$').</p>

  <p>Furthermore, because @('and') macroexpands to an @('if')-term and beta
  reduction eliminates local variable names it would rewrite</p>

  @({
  (loop$ for rest on (aaa aa)
         thereis
         (let ((z (cdr rest)))
           (and (atom z) rest))
  })

  <p><b>But not all such problems can be solved by switching between rewriting
  quoted @('lambda') objects and just cleaning them up!</b></p>

  <p>Consider this rewrite rule.  The @('thereis') @('loop$') in the lefthand
  side of the rule below is exactly the @('loop$') whose translation we showed
  at the beginning of this topic.  The cleaned up internal form of the lefthand
  side is the @('thereis$+') term shown by the first @(':tc') display in this
  topic.  The rule below says that the @('thereis') @('loop$') in question
  computes @('member').</p>

  @({
  (defthm loop$-can-be-member
     (equal (loop$ for x on a
                   thereis
                   (if (equal (car x) b) x nil))
            (member b a)))
  })

  <p>You might expect that when the rewriter encounters (an instance of) such a
  @('loop$') it will replace it by a @('member') term.  That is actually
  true!</p> <p>For example, if we then tried to prove a conjecture
  mentioning</p>

  @({
  (loop$ for x on aaa
         thereis
         (if (equal (car x) bbb) x nil))
  })

  <p>the @('loop$-can-be-member') rule would fire and replace that @('loop$')
  by @('(member bbb aaa)').</p>

  <p>But it is easy to misjudge whether a given @('loop$') is an instance of
  another.</p>

  <p>Suppose our goal conjecture contained</p>

  @({
  (loop$ for x on (aaa aa)
         thereis (if (equal (car x) (bbb bb)) x nil))
  })

  <p>This @('loop$') looks like the @('loop$') in @('loop$-can-be-member')
  except we've used @('(aaa aa)') instead of @('a'), and @('(bbb bb)') instead
  of @('b').</p>

  <p>Will that @('loop$') be rewritten to @('(member (bbb v) (aaa u))')?
  No!</p>

  <p>To understand why not, we first have to compare the internal forms of the
  two @('loop$')s.  Recall that the lefthand side of rewrite rules are cleaned up
  before storage, so the internal form of the lefthand side of
  @('loop$-can-be-member') is in fact the @('thereis$+') term produced by
  @(':tc') above.  If we are either rewriting @('lambda') objects or just
  syntactically cleaning @('lambda') objects in the proof we're looking at, the
  the internal forms of the @('loop$') in the conjecture will be just the
  @(':tc') of that @('loop$') (because there's nothing interesting to rewrite
  here).  So here is the lefthand side of the rule side-by-side with the
  rewritten target in the conjecture.  We have highlighted the differences in
  uppercase and numbered the lines that contain differences.</p>

  @({
  lhs of rule                   target
  (thereis$+                    (thereis$+
   '(lambda                      '(lambda
      (loop$-gvars loop$-ivars)     (loop$-gvars loop$-ivars)
      (if (equal                    (if (equal
           (car (car loop$-ivars))       (car (car loop$-ivars))
           (CAR LOOP$-GVARS))            (BBB (CAR LOOP$-GVARS))) ; [1]
          (car loop$-ivars)             (car loop$-ivars)
          'nil))                        'nil))
   (cons B 'nil)                 (cons BB 'nil)                   ; [2]
   (loop$-as                     (loop$-as
    (cons (tails A) 'nil)))       (cons (tails (AAA AA)) 'nil)))  ; [3]
  })

  <p>Note that the target is not an instance of the lefthand side of the rule
  &mdash; but only because of the difference on line [1].  Lines [2] and [3] of
  the lefthand side can be instantiated to become those lines in the target.
  But because of [1] our @('loop$-can-be-member') rule will not rewrite the
  target shown here.</p>

  <p>This kind of problem cannot be fixed by fiddling with how the prover
  treats @('lambda') objects.  Instead, we need to transform the target
  @('lambda') object into the functionally different @('lambda') object in the
  rule while simultaneously changing how @('thereis$+') applies it.  In
  particular we need to transform @('target') to @('target'') below by moving
  the @('BBB') out of [1] and into [2] as shown below.</p>

  @({
  target                         target'
  (thereis$+                     (thereis$+
   '(lambda                       '(lambda
      (loop$-gvars loop$-ivars)      (loop$-gvars loop$-ivars)
      (if (equal                     (if (equal
           (car (car loop$-ivars))        (car (car loop$-ivars))
           (BBB (CAR LOOP$-GVARS)))       (CAR LOOP$-GVARS))      ; [1]
          (car loop$-ivars)              (car loop$-ivars)
          'nil))                         'nil))
   (cons BB 'nil)                 (cons (BBB BB) 'nil)            ; [2]
   (loop$-as                      (loop$-as
    (cons (tails (aaa aa)) 'nil))) (cons (tails (aaa aa)) 'nil)))
  })

  <p>Note that @('target'') is in fact an instance of the lefthand side of the
  rule.  But we've changed the semantics of the @('lambda') object and changed
  the way @('thereis$+') uses it by moving the @('BBB') from the inside to the
  outside of the @('lambda').  No @('lambda') rewriting can do this.  Instead,
  we need a rule that rewrites @('thereis$+').  (In fact, a great project would
  be to implement a metafunction that does this kind of optimization for all
  @('loop$') scions.  We just haven't done that yet.  Let us know if you
  do!)</p>

  <p>Here is a suitable rewrite rule for this particular instance of this
  phenomenon.  We write it as a @('thereis') @('loop$') rule rather than a
  @('thereis$+'), but they're the same.</p>

  @({
  (defthm example-of-constant-subterm-abstraction
  (implies (warrant bbb)
           (equal (loop$ for xxx on a
                         thereis
                         (if (equal (car xxx) (bbb bb)) xxx nil))
                  (let ((zzz (bbb bb)))
                    (loop$ for xxx on a
                           thereis
                           (if (equal (car xxx) zzz) xxx nil))))))
  })

  <p>This illustrates another lesson.  Remember that we're imagining a proof of
  some conjecture that involves a @('thereis') @('loop$') mentioning @('BBB')
  and wondering whether our rewrite rule @('loop$-can-be-member') will hit it.
  Had the @('thereis') @('loop$') in the conjecture been written in the style
  of the @('let') expression above, where a variable is bound to @('(bbb bb)')
  and then that variable used in the @('loop$') body, we wouldn't need to move
  the @('(bbb bb)') out.  Instead, the @('lambda') generated by translating the
  @('loop$') would contain a variable instead of @('(bbb bb)').  The name of
  the @('let')-bound variable outside the @('lambda') is irrelevant since it
  won't appear in the cleaned up @('lambda') object where it is replaced by a
  component of the global variables @('LOOP$-GVARS').  In the containing
  @('thereis$+') the value of that global variable will be @('(bbb bb)'), which
  means the free variable @('b') in our @('loop$-can-be-member') rule can be
  instantiated with @('(bbb bb)') to allow the rule to match.</p>

  <p>Put another way, by writing the @('loop$') in the inefficient
  way (requiring @('(bbb bb)') to be recomputed on every iteration) we
  implicitly produce @('lambda') object that is less general than one with the
  @('(bbb bb)') on the outside.</p>

  <p><b>Keep unchanging subterms of @('loop$') bodies as variables and compute
  their values outside of the @('lambda').</b> Basically, try to write the most
  general @('lambda') objects you can.</p>

  <p>Finally, these difficulties are exacerbated by the ease with which
  @('loop$') statements can be written and the difference between their
  appearance and the formal terms they denote.  You might be more successful at
  learning to use @('loop$')s in lemmas and theorems if you simply <b>don't use
  @('loop$')!</b> Instead, learn to write the corresponding terms, e.g., try
  writing a @('thereis$') or a @('thereis$+') term instead of a @('thereis')
  @('loop$') statement in your lemmas and theorems.  Since the prover's output
  contains such terms (rather than @('loop$') statements), it will be easier to
  see where lemmas differ from the targets they were intended to hit.  After
  enough practice you can write @('loop$') statements with a better
  appreciation of what they actually denote.</p>")
other
(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)")
other
(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)")
other
(defxdoc rule-classes
  :parents (acl2)
  :short "Adding rules to the database"
  :long "<p>For an introduction to rule-classes, see @(see
  rule-classes-introduction).</p>

  @({
  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 REWRITE-QUOTED-CONSTANT),
 @(':')@(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') (see @(see well-founded-relation-rule)).  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
                                         or :class = :REWRITE-QUOTED-CONSTANT
    :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>When in doubt, create a @(':')@(tsee rewrite) rule, which is the default.
 See @(see rule-classes-introduction).</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: 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) or @(':')@(tsee rewrite-quoted-constant).  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>")
other
(defxdoc rule-classes-introduction
  :parents (rule-classes)
  :short "Selecting which kind of rule to create"
  :long "<p>Successful ACL2 users generally direct many of their proved
 theorems to be stored as rules, which can be applied automatically in
 subsequent proof attempts.  See @(see rule-classes) for a detailed discussion
 of the kinds of rules that can be created.  Here, we give a brief introduction
 to rule-classes that may suffice for most ACL2 users.</p>

 <p>The workhorse for ACL2 proof attempts is generally the application of @(see
 rewrite) rules.  When you prove a theorem stated with @(tsee defthm), ACL2
 stores it as a rewrite rule unless either the @(':rule-classes') keyword is
 supplied explicitly or an error occurs because the theorem is not in a form
 that ACL2 knows how to store as a rewrite rule.  See @(see rewrite) for an
 introduction to rewrite rules in ACL2.  That topic also has links to useful
 introductory material as well as a notion of @(see congruence), which allows
 the rewriting of one term to another when the two are merely equivalent in
 some suitable sense, but not necessarily equal.</p>

 <p>Most successful ACL2 users make only sparing use of other kinds of rules
 besides rewrite rules.  When in doubt, the default is probably best: the
 absence of any @(':rule-classes') keyword in a @(tsee defthm) event, which
 is equivalent to @(':rule-classes :rewrite').  Below are some suggestions for
 when other kinds of rules might be appropriate.  Of course, you are welcome to
 scan the @(see community-books) for examples.  One can for example find many
 examples (apparently more than 15,000) of @(':type-prescription') rules by
 standing in the @('books/') directory and issuing the following shell
 command (Linux or MacOS):</p>

 @({
 time egrep -e ':rule-classes .*type-prescription' --include='*.l*sp' -ri .
 })

 <p>Below, we sometimes speak of the ``conclusion'' of a formula.  For many
 rule classes, this is simply the formula itself unless the formula is of the
 form @('(implies hyp concl)'), in which case it is recursively the conclusion
 of @('concl').  See the subtopics of @(see rule-classes) for detailed
 documentation.</p>

 <ul>

 <li>If the conclusion is a call of a primitive recognizer or a compound
 recognizer, or the negation of such &mdash; for example, @('(true-listp (f x
 y))') &mdash; consider making a @(see type-prescription) rule.  (For relevant
 background on recognizers, see @(see compound-recognizer), which also
 describes how to make a rule that designates a function as a
 compound-recognizer.)  But note that hypotheses of such a rule are
 proved (``relieved'') by ACL2 only using <see topic='@(url
 type-reasoning)'>type reasoning</see>.  If you want rewriting to be used for
 relieving the hypotheses, you can wrap them in @(tsee force) or @(tsee
 case-split).</li>

 <li>If the conclusion is an inequality or negated inequality, consider making
 a @(see linear) rule, but generally only if you can identify a reasonable
 maximal term, which very roughly is a syntactically largest term that binds all
 the variables.  For example, the formula @('(< (f x y) (g y z))') might not
 make a good linear rule.  For a more careful discussion of maximal terms, see
 @(see linear).</li>

 <li>If the formula is a term in normal form (not simplifiable by your rewrite
 rules) that tends to be an explicit hypothesis in some of your theorems,
 consider making it a @(see forward-chaining) rule.  For example, if you are
 reasoning about a finite state machine (such as an interpreter) and your
 theorems tend to have the hypothesis @('(good-state-p st)'), and your formula
 is @('(good-state-p (foo st))'), then that formula is a good candidate for a
 @(see forward-chaining) rule.</li>

 <li>If the rule looks like a recursive definition @('(equal (f x1 x2 ..)
 (... (f ...) ...))'), consider making a @(see definition) rule.</li>

 <li>When you want to control the simplifier rather than just turning rules
 (especially rewrite rules) loose on your terms, consider using @(see meta)
 rules or @(see clause-processor) rules.</li>

 </ul>

 <p>There are other rule classes that can be useful.  See @(see rule-classes)
 for a complete list.</p>")
other
(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>")
other
(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.  (ACL2's notion of ``smaller'' here is essentially ordinary
 natural-number @('<'), and the argument @('x') is measured by applying
 function @(tsee acl2-count) to @('x'); see @(see defun).)  However, by default
 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; it considers only rulers, as we now
 discuss.</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 &mdash; that is, tests and their negations that are collected by walking
 through the true and false branches of @('IF') calls, starting at the top.
 Consider for example the following term, where @('foo') is assumed to be a
 function symbol.</p>

 @({
 (if a
     (if (if b c d) e f)
   (if g
       (foo (if h i j))
     k))
 })

 <p>For the occurrence of @('c') in that term, the only ruler is @('a'); but
 both @('a') and @('b') are governors.  For the occurrence of @('i'), @('(not
 a)') and @('g') are the only rulers; but its governors are @('(not a)'),
 @('g'), and @('h').</p>

 <p>We have seen that for a subterm occurrence in a term, every ruler is a
 governor but not necessarily vice-versa.  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 the discrepancy between rulers and governors is to
 ``lift'' the @('IF') test to the top level.  We can apply that technique to
 the @('defun') of @('f') above, 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 three basic
 ruler-extenders: @(tsee RETURN-LAST), which comes from macroexpansion of calls
 of @(tsee PROG2$), @(tsee EC-CALL), and others; @(tsee MV-LIST); and @(tsee
 IF), which affects termination analysis through the first argument of calls of
 @('IF') (it continues through the true and false branches of these calls even
 without @('IF') being among the ruler-extenders).</p>

 <p>IMPORTANT REMARKS.</p>

 <ol>

 <li>Notice that the argument to @('set-ruler-extenders') is evaluated, but the
 argument to @(':RULER-EXTENDERS') in @('XARGS') is not evaluated.</li>

 <li>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.</li>

 <li>Also please note that by taking advantage of the ruler-extenders, you may
 change the induction scheme computed for the function.  This is especially
 worth remembering for functions containing @(tsee let) or @(tsee let*)
 expressions (which translate to @(tsee lambda) applications; see @(see term)).
 If the induction scheme suggested by such a function seems to provide more
 induction hypotheses than appear necessary, it might help to admit the
 function with @(':lambdas') included among the ruler extenders even if that is
 not necessary for the termination proof.  This can cause the induction scheme
 to have a richer case analysis with fewer induction hypotheses on any given
 induction step.  While this can make it more difficult for the system to merge
 induction schemes to get an appropriate induction, it can also make the proof
 of each induction step easier.  Unfortunately, we have no more precise advice
 as to exactly when adding @(':lambdas') will help.  See @(see
 induction-coarse-v-fine-grained).</li>

 </ol>

 <p>To see the ruler-extenders of an existing function symbol, @('fn'), in a
 logical @(see world), @('wrld'), evaluate @('(get-ruler-extenders 'fn wrld)')
 after @('(include-book
 "std/system/get-ruler-extenders" :dir :system)').  For example,
 evaluation of @('(get-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) @(tsee MV-LIST), and @(tsee IF).  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>")
other
(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>")
other
(defxdoc running-acl2-without-executable
  :parents (installation-support)
  :short "Running ACL2 without building an executable image"
  :long "<p>The most convenient way to use ACL2 is first to install an
 executable image; see @(see creating-executable).  However, in some cases this
 is not possible, for example, perhaps if you are using a trial version of a
 Common Lisp implementation.  In that case you should follow the steps below
 each time you want to start up ACL2.</p>

 <p>We assume you have obtained ACL2 and placed it in your current directory.
 Start up your Common Lisp in that directory, and compile by executing the
 following forms.  <i>This sequence of steps needs to be performed only
 once.</i></p>

 @({
 (load "init.lisp")
 (in-package "ACL2")
 (compile-acl2)
 })

 <p>Now each time you want to use ACL2, execute the following forms after
 starting up Common Lisp in that same directory.  This may take a minute or
 two.</p>

 @({
 (load "init.lisp")
 (in-package "ACL2")
 (load-acl2)
 (initialize-acl2)
 (lp) ; enter the ACL2 read-eval-print loop
 })

 <p>Now see @(see using-acl2).</p>")
other
(defxdoc rw-cache-state
  :parents (rewrite)
  :short "The current rw-cache-state"
  :long "<p>See @(tsee set-rw-cache-state) for background on the
 <i>rw-cache</i>, which saves failed attempts to apply conditional @(see
 rewrite) rules.  To get the current rw-cache-state, evaluate the following
 form.</p>

 @({
 (rw-cache-state (w state))
 })")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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!  (On a related note: For
 discussion about unsoundness when converting such @(see program)-mode
 functions to @(see logic) mode, see @(see program-only).)</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 !>
 })")
other
(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).  But note that this
 skips memoization settings that are either derived from calls of @(tsee
 memoize-partial) or have a non-@('nil') value of @(tsee memoize) argument
 @(':invoke')</p>

 <p>Also see @(see restore-memoization-settings).</p>")
other
(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>

 <p>At the end of this topic we discuss how to use the `@('make')' utility to
 invoke @('save-exec').</p>

 @({
  Examples:

  ; Save an executable script named my-saved_acl2, with the indicated message
  ; added below the words "MODIFICATION NOTICE" under 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 under the modification
  ; notice:
  (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 @(':')@(tsee 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.  If
 @('inert-args') is supplied a string, then although those arguments will be
 appended to the supplied arguments (see (5) below), they will be ignored by
 the host Lisp (except for being recorded; see (6) below).  @('Inert-args') is
 @('nil') by default (that is, when omitted).  The other legal value of
 @('inert-args'), @('t'), is discussed in (5) below.  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>


 <p>Finally, note that @('save-exec') can be invoked using the `@('make')'
 utility in the main ACL2 directory by using the @('save-exec') target.  That
 target will first build an ACL2 executable in the normal way if it is out of
 date.  Then it will start that executable, using the value of
 @('ACL2_CUSTOMIZATION') (as a `@('make')' or environment variable) &mdash;
 which must be specified &mdash; as the @(see acl2-customization) file, before
 making a @('save-exec') call.  By default, that call is @('(save-exec
 "custom-saved_acl2" "Saved with additions from <file>")'), where
 @('<file>') is the value of @('ACL2_CUSTOMIZATION').
 (Except, in ACL2(p) and ACL2(r), @('"custom-saved_acl2"') is replaced by
 @('"custom-saved_acl2p"') and @('"custom-saved_acl2r"'), respectively.)
 However, you can specify the first argument as the value of @('ACL2_SAVED')
 (as a `@('make')' or environment variable), and you can specify the remaining
 arguments as the value of @('ACL2_SAVED_ARGS') (also as a `@('make')' or
 environment variable).  Here is an example one could run at the shell prompt;
 notice the careful quoting.</p>

 @({
 make save-exec \
   ACL2_CUSTOMIZATION=~/temp/foo.lsp \
   ACL2_SAVED=my-acl2 \
   ACL2_SAVED_ARGS='"My custom image" \
                    :init-forms (quote ((defun foo (x) (reverse x))))'
 })

 <p>WARNING: It is a good idea to look at the log file noted in the `@('make')'
 output, to check that your customization file loaded as intended (presumably,
 without errors).</p>")
other
(defxdoc saving-event-data
  :parents (system-utilities output-controls)
  :short "Save data stored for subsidiary @(see events)"
  :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>

 @({
 General Forms:
 (saving-event-data form)

 ; See Further information below for keyword options for these two:
 (runes-diff book-name)
 (old-and-new-event-data book-name)
 })

 <p>where @('form') is any form that evaluates to an @(see error-triple) and
 @('book-name') is a file ending with @('".lisp"').  See below for typical
 usage.</p>

 <p>A common problem is that a book whose certification formerly succeeded now
 has a certification failure.  In that case, the failure is often caused by a
 proof failure; then one may wish for information on what has changed from the
 previous, successful proof attempt and the new, failing proof attempt.  Here
 is a procedure for obtaining such information.  After that we discuss some
 variations on that procedure.</p>

 <h3>Finding @(see rune)s that were used only previously, or only now</h3>

 <p>Here we discuss a procedure for discovering, given a book @('BOOK.lisp'),
 which @(see rune)s were used in a previous successful proof but not in the new
 failed proof attempt, or vice-versa.</p>

 <p>The procedure described here requires certain &ldquo;event-data&rdquo;
 information to have been written by a previous certification of
 @('BOOK.lisp').  Such writing of event-data can be accomplished by providing
 @(tsee certify-book) the keyword argument @(':write-event-data t').  Writing
 of event-data by @('certify-book') can also be accomplished by setting
 environment variable @('ACL2_WRITE_EVENT_DATA') to a non-empty value, though
 that is overridden if @(tsee certify-book) keyword argument
 @(':write-event-data') is explicitly supplied the value, @('nil').  See @(see
 build::custom-certify-book-commands) for discussion about how a
 @('cert-flags') comment can set @('certify-book') keyword values when using
 the @('cert.pl') utility.</p>

 <p>When @('certify-book') writes event-data under either condition above
 (keyword argument or environment variable), it writes it to
 @('BOOK@event-data.lsp').  That file includes entries of the form @('(name
 . alist)'), where @('alist') is an <i>event-data alist</i> &mdash; see @(tsee
 get-event-data) &mdash; where each entry corresponds to one of the following
 event types, possibly generated by a macro or @(tsee make-event) call.</p>

 <ul>
 <li>defthm</li>
 <li>defun</li>
 <li>verify-guards</li>
 <li>thm</li>
 </ul>

 <p>One @('(name . alist)') entry is written for each such event, in the order
 in which the events were encountered during the proof pass of certification.
 Normally @('name') is the name of the event, but it is @('nil') in the case of
 a @(tsee thm) event.</p>

 <p>Suppose that you have file @('BOOK@event-data.lsp') as discussed above,
 that is, from having previously certified @('BOOK.lisp') when writing
 event-data.  Also suppose that you now have a copy of @('BOOK.lisp') (maybe
 the same one, maybe not) for which certification has failed, possibly using a
 different ACL2 version than the first, and let @('EV') be the event that
 caused the failure; assume that's because of a proof failure.  Below are steps
 that allow you to see which rules (actually, @(see rune)s) were used in the
 proof attempt for the first event but not the second, or vice-versa.  That
 information might help you to repair the proof, for example by enabling or
 disabling a rule whose @(see enable)d status has changed after the successful
 certification, or by proving a rule that was in an included book during the
 successful certification but has since been deleted.</p>

 <p><b>Step 1</b>.  Load the @(see portcullis) commands:</p>

 @({
 (ld "BOOK.port")
 })

 <p><b>Step 2</b>.  Execute the following command, which will presumably end
 with a failed proof for the event, @('EV').</p>

 @({
 (saving-event-data (ld "BOOK.lisp"))
 })

 <p><b>Step 3</b>.  See which runes were used in the old proof and not the new,
 and vice-versa, respectively:</p>

 @({
 (runes-diff "BOOK.lisp")
 })

 <p>An example is in @(see community-books) file
 @('books/demos/event-data/test1.lisp'), which has comments that lead through a
 variant of the steps above.  File @('test1-input.lsp') in that directory
 actually carries out that process, resulting in output displayed in log file
 @('test1-log.txt') in that directory.  Here is the output of a @('runes-diff')
 call shown both in that log file and in a comment in file
 @('test1-input.lsp').  It shows that a @(see type-prescription) rule, named
 @('true-listp-append'), was used in the original proof but not the failed
 proof (which made the @(tsee ld) call of Step 2 above without first
 performing Step 1, which would have introduced that type-prescription rule).
 This output also shows that the new (failed) proof attempt used many runes not
 used in the previous proof &mdash; not surprisingly, since without the rule
 @('true-listp-reverse') the prover made a desperate attempt involving
 destructor elimination and induction.</p>

 @({
  ((:OLD ((:TYPE-PRESCRIPTION TRUE-LISTP-REVERSE)))
   (:NEW ((:DEFINITION ALISTP)
          (:DEFINITION ATOM)
          (:DEFINITION NOT)
          (:DEFINITION TRUE-LISTP)
          (:ELIM CAR-CDR-ELIM)
          (:EXECUTABLE-COUNTERPART CONSP)
          (:EXECUTABLE-COUNTERPART NOT)
          (:EXECUTABLE-COUNTERPART REVERSE)
          (:FAKE-RUNE-FOR-TYPE-SET NIL)
          (:INDUCTION ALISTP))))
 })

 <p>A second, analogous set of three files is in that same directory; just
 replace @('"test1"') by @('"test2"') in the filenames.</p>

 <h3>Further information</h3>

 <p>The @('runes-diff') utility is intended to serve as an example of a class
 of such query utilities.  It is a macro that expands to a corresponding
 function call.</p>

 @({
 ACL2 !>:trans1 (runes-diff "BOOK.lisp")
  (RUNES-DIFF-FN "BOOK.lisp" NIL NIL NIL 'RUNES-DIFF
                 STATE)
 ACL2 !>
 })

 <p>@('Runes-diff-fn') is actually quite simple.</p>

 @(def runes-diff-fn)

 <p>It is simple because the real work is carried out using a more complex
 function, @('old-and-new-event-data-fn').  That function returns a pair
 @('(old . new)'), where @('old') and @('new') are event-data alists for the
 failed event (called @('EV') above).  Then @('runes-diff-fn') only needs to
 pick out the @('RULES') fields and form the set-differences.</p>

 <p>The macro @('old-and-new-event-data') provides a convenient interface to
 @('old-and-new-event-data-fn').</p>

 @({
 ACL2 !>:trans1 (old-and-new-event-data "BOOK.lisp")
  (OLD-AND-NEW-EVENT-DATA-FN "BOOK.lisp"
                             NIL NIL NIL 'OLD-AND-NEW-EVENT-DATA
                             STATE)
 ACL2 !>
 })

 <p>Both @('runes-diff') and @('old-and-new-event-data') have keyword arguments
 that allow one to choose a specific name for a failed event &mdash; the most
 recent event with that name, rather than @('EV') &mdash; and a directory for
 the given filename, which may be a string or a keyword representing a project
 directory (see @(see project-dir-alist)).  The @('"test2"') files mentioned
 above have an example in which the name @('nil') is supplied to specify the
 @(tsee thm) event most recently preceding the failed event (actually it's the
 only one preceding the failed event).</p>

 @({
 General Forms:
 (runes-diff book-string &key name dir)
 (old-and-new-event-data book-string &key name dir)
 })

 <p>If you want to use these programmatically, call the corresponding
 @('"-FN"') versions, where @('namep') is @('t') to represent the case that a
 name is provided, else @('nil').</p>

 @({
 General Forms:
 (runes-diff-fn book-string name namep dir ctx state)
 (old-and-new-event-data book-string name namep dir ctx state)
 })")
other
(defxdoc sbcl-installation
  :parents (obtaining-common-lisp)
  :short "Installing Steel Bank Common Lisp (SBCL)"
  :long "<p>SBCL is available from <tt><a
 href='https://www.sbcl.org'>https://www.sbcl.org</a></tt>.  You can of course
 go to that website to find download and installation instructions for SBCL,
 but below is a concise summary that includes build options appropriate for
 ACL2.</p>

 <p><b>NOTE:</b> If you already have a previous version of SBCL installed and
 you have experience with Lisp, you might want to see @(see
 sbcl-installation-brief) for abbreviated instructions to use instead of those
 below.</p>

 <ol>

 <li>Download an SBCL binary from
 <tt><a href='https://www.sbcl.org/platform-table.html'>https://www.sbcl.org/platform-table.html</a></tt>.
 That page contains a table
 with  combinations of operating systems and hardware architectures,
 from which you have to pick the one that applies to you.
 Note that you need an SBCL binary
 in order to compile from source (see below).
 The file downloaded from the table will have a name like
 @('sbcl-2.1.2-arm64-darwin-binary.tar.bz2'),
 where the @('arm64-darwin') part depends on
 the chosen combination of operating system and hardware architecture.</li>

 <li>Untar the file in a directory of your choice,
 which will create a subdirectory with a name like
 @('sbcl-2.1.2-arm64-darwin'),
 consistently with the name of the downloaded file.</li>

 <li>Change to that subdirectory and run
 @({sh run-sbcl.sh})
 to make sure that the binary works.
 On macOS, you may get a pop-up saying that
 Apple cannot check it for malware and that it needs to be updated.
 In that case, open the macOS settings,
 go under `Privacy and Security'
 (or `Security and Privacy', depending on macOS version),
 and you should see something about the (SBCL) executable
 whose execution was stopped:
 click the button to allow it, and retry running it.
 Eventually it should work.</li>

 <li>In the same directory where you just ran SBCL, run the SBCL installer.
 This is done via
 @({INSTALL_ROOT=... sh install.sh})
 where @('...') is optional: if omitted, it defaults to @('/usr/local').
 If you pick something different from this default,
 note that the installer will create three directories there,
 namely @('bin'), @('lib'), and @('share').
 Thus, for examples, if you want to install SBCL in your home,
 you may want to create a directory in your home (e.g. @('sbcl'), or @('apps')),
 and pass that as @('INSTALL_ROOT'),
 instead of passing your home directory.</li>

 <li>Add that @('bin') directory to your path, so that SBCL can be found.
 Try running @({sbcl}) to make sure that the installed binary works.
 This time macOS should not block its execution.</li>

 <li>Download the SBCL source from
 <tt><a href='https://www.sbcl.org/platform-table.html'>https://www.sbcl.org/platform-table.html</a></tt>,
 the same page with the table of binaries.
 There should be one link to the sources, above the table of binaries.
 The downloaded file will have a name like @('sbcl-2.3.9-source.tar.bz2').</li>

 <li>Untar the file in a directory of your choice,
 which will create a subdirectory with a name like @('sbcl-2.3.9').</li>

 <li>Change to that subdirectory, and compile SBCL via:

 @({sh make.sh --without-immobile-space --without-immobile-code --without-compact-instance-header})

 You might also need option @('--with-sb-thread'); this has been necessary on a
 machine running FreeBSD.
 These options prevent certain possible errors.
 The compilation process prints a lot of stuff on the screen,
 and should succeed.</li>

 <li>The final part of the screen output will suggest
 to run the tests, via:
 @({cd ./tests && sh ./run-tests.sh})
 They will take a while, but should eventually succeed.</li>

 <li>The final part of the screen output will also suggest
 to build the documentation, via @({cd ./doc/manual && make})
 &mdash; this may fail, but that does not seem to matter.</li>

 <li>Finally, install the just compiled SBCL
 in the same way as the downloaded binary above, via:
 @({INSTALL_ROOT=... sh install.sh})
 If you use the same @('...') as above (or use the default if you did before),
 the new installation will replace the old one,
 and invoking SBCL (which will still be on the path)
 will run the newly compiled version.</li>

 <li>If a new version of the SBCL sources becomes available,
 you can repeat the procedure above to compile and install it,
 using the previously installed binary.</li>

 <li>As an alternative to installing the binary compiled from the sources,
 you could create a script, in your executable path, containing
 @({
 #!/bin/sh
 <dir>/run-sbcl.sh --dynamic-space-size 2000 "$@"
 })
 where @('<dir>') is the untarred directory described above,
 and where the dynamic space size option is just an example
 of how one can pass options to the running SBCL,
 but it is not necessarily needed.
 If you need to pass options like this,
 you can also do that if you follow the installation instructions:
 in that case, the script should contain just @('sbcl')
 instead of @('<dir>/run-sbcl.sh').</li>

 </ol>")
other
(defxdoc sbcl-installation-brief
  :parents (obtaining-common-lisp)
  :short "Installing Steel Bank Common Lisp (SBCL)"
  :long "<p>The topic @(see sbcl-installation) contains full installation
 instructions for SBCL.  The present topic contains abbreviated instructions
 that have been used successfully over time; these may be suitable for those
 who already have a previous version of SBCL installed and have experience with
 Lisp.  If the instructions below are not sufficient for you, please see @(see
 sbcl-installation) instead.</p>

 <p>SBCL is available from <tt><a
 href='https://www.sbcl.org'>https://www.sbcl.org</a></tt>.  You can of course
 go to that website to find download and installation instructions for SBCL,
 but here is a concise summary that includes build options appropriate for
 ACL2.</p>

 <ol>

 <li>Download SBCL from <tt><a
 href='https://www.sbcl.org'>https://www.sbcl.org</a></tt>.  A shortcut may be
 to follow the &ldquo;<b>Source</b>&rdquo; link near the top of the page,
 <tt><a
 href='https://www.sbcl.org/platform-table.html'>https://www.sbcl.org/platform-table.html</a></tt>.</li>

 <li>The downloaded file will have a name like
 &ldquo;@('sbcl-2.2.10-source.tar.bz2')&rdquo;, where &ldquo;@('2.2.10')&rdquo;
 is replaced by the current SBCL version.  Change to a directory just above
 where you want SBCL to reside and move the downloaded file there.</li>

 <li>Extract the downloaded file (where it now resides), for example as follows
 (again, where &ldquo;@('2.2.10')&rdquo; is replaced by the current SBCL
 version number).

 @({
 tar jxf sbcl-2.2.10-source.tar.bz2
 })</li>

 <li>Change to the new directory and build SBCL with options appropriate for
 ACL2, as follows (again, replacing &ldquo;@('2.2.10')&rdquo; as appropriate).

 @({
 cd sbcl-2.2.10
 sh make.sh --without-immobile-space --without-immobile-code --without-compact-instance-header
 })

 You might also need option @('--with-sb-thread'); this has been necessary on a
 machine running FreeBSD.</li>

 <li>Create a script file in a directory that is on your path (or, if you are
 updating your sbcl, just replace your current sbcl script; you can find its
 location by executing the command, &ldquo;@('which sbcl')&rdquo;).  If you are
 in directory @('<DIR>') from the preceding step (e.g., a path ending in
 &ldquo;@('sbcl-2.2.10')&rdquo;), then that script file should contain the
 following lines.

 @({
 #!/bin/sh
 <DIR>/run-sbcl.sh --dynamic-space-size 2000 "$@"
 })</li>

 </ol>")
other
(defxdoc scion
  :parents (apply$)
  :short "A function ancestrally dependent on @('apply$')"
  :long "<p>The function @('fn') is a <i>scion of</i> @('apply$') or simply a
  <i>scion</i> if the function is ancestrally dependent on @('apply$').  That
  is, @('fn') is @('apply$'), or @('fn') calls @('apply$'), or calls a function
  that calls @('apply$'), or calls a function that calls a function that calls
  @('apply$'), etc.</p>

  <p>Meriam-Webster defines <i>scion</i> as ``a descendant of a wealthy,
  aristocratic, or influential family.''</p>

  <p>Examples of scions include @('apply$'), @('collect$') and @('foldr'), where
  the last two are defined as shown below.</p>

  @({
  (defun$ collect$ (fn lst)
    (if (endp lst)
        nil
        (cons (apply$ fn (list (car lst)))
              (collect$ fn (cdr lst)))))

  (defun$ foldr (lst fn init)
    (if (endp lst)
        init
        (apply$ fn
                (list (car lst)
                      (foldr (cdr lst) fn init)))))
  })

  <p>Note: @('Collect$'), which is part of the support for the @(tsee loop$)
  statement, is pre-defined in ACL2 but @('foldr') is not.</p>

  <p>Most often, scions treat one or more of their arguments as ``functions,''
  i.e., have at least one formal of ilk @(':FN').  But that is not necessarily
  the case.  @('Collect$-squares'), as defined below,</p>

  @({
  (defun$ collect$-squares (lst)
    (collect$ (lambda$ (x) (* x x)) lst))
  })

  <p>is a scion even though it does not have a formal of ilk @(':FN').
  However, it calls the scion @('collect$').</p>

  <p>The function defined by</p>

  @({
  (defun$ collect$-expr (x lst alist)
    (if (endp lst)
        nil
        (cons (ev$ x (cons (cons 'v (car lst)) alist))
              (collect$-expr x (cdr lst) alist))))
  })

  <p>is a scion because it calls @('ev$') which calls @('apply$') in the
  mutually recursive clique that defines them both.  Note that the ilks of the
  formals of @('collect$-expr') are @(':EXPR'), @('NIL') and @('NIL'),
  respectively.  The function collects the successive values of the expression
  @('x') under extensions of @('alist') binding the variable symbol @('v') to
  successive elements of @('lst').</p>

  <p>In the early days of @('apply$') we used the term ``mapping function'' to
  refer to scions.  But that nomenclature was misleading because in the Lisp
  culture ``mapping'' tends to be understood as a kind of linear iteration.</p>

  <p>Fans of higher order logic have suggested we use the term ``functional''
  for our scions, or at least for those scions having at least one formal of
  ilk @(':FN').  However, we have resisted that suggestion because a functional
  takes a function as an argument and is thus a higher-order entity, but ACL2
  is first-order, functions are never objects in ACL2, and the values of our
  @(':FN') formals are ordinary objects like symbols and lists that are
  interpreted as functions.</p>")
other
(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.</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)")
other
(defxdoc second
  :parents (nth acl2-built-ins)
  :short "Second member of the list"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(defxdoc set-absstobj-debug
  :parents (defabsstobj)
  :short "Get more information when atomic update fails 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 the following error message, and how to
 add information to the end of it.</p>

 @({
 ACL2 Error in CHK-ABSSTOBJ-INVARIANTS:  Possible invariance violation
 for an abstract stobj!
 **PROCEED AT YOUR OWN RISK.**
 To proceed, evaluate the following form.
 :CONTINUE-FROM-ILLEGAL-STATE
 See :DOC set-absstobj-debug.
 })

 <p>Advanced users who are willing to risk unsound invariance violations to get
 a bit more speed may submit the following when there is an active trust
 tag (see @(see defttag)).</p>

 @({
 (set-absstobj-debug :ignore)
 })

 <p>The rest of the session will then avoid the error message above because it
 avoids the abstract stobj invariance checking discussed below.  BUT WITHOUT
 THIS CHECKING, YOUR SESSION COULD BE CORRUPTED!  The discussion below assumes
 that you are not using the special argument @(':ignore') for
 @('set-absstobj-debug').</p>

 <p>The use of @('(set-absstobj-debug t)') will make the error message above
 more informative, for example as follows, at the cost of slower execution
 &mdash; but in practice, the slowdown may be negligible (more on that
 below).  Below, only the last two lines are new.</p>

 @({
 ACL2 Error in CHK-ABSSTOBJ-INVARIANTS:  Possible invariance violation
 for an abstract stobj!
 **PROCEED AT YOUR OWN RISK.**
 To proceed, evaluate the following form.
 :CONTINUE-FROM-ILLEGAL-STATE
 See :DOC set-absstobj-debug.
 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 @(see community-books) file
 @('books/demos/defabsstobj-example-4-input.lsp') for how to do that.
 (The corresponding output file @('books/demos/defabsstobj-example-4-log.txt')
 may also be informative.)</p>

 @({
  Examples:
  (set-absstobj-debug t)                 ; obtain extra debug info, as above
  (set-absstobj-debug nil)               ; avoid extra debug info (default)
  (set-absstobj-debug :ignore)           ; possibly unsound! -- see above

  General Form:
  (set-absstobj-debug val)
 })

 <p>where @('val') is evaluated.</p>

 <p>Recall (see @(see defabsstobj)) that for any exported function whose
 @(':EXEC') function might (according to ACL2's heuristics) modify the
 foundational 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>Calls of @('set-absstobj-debug') are legal event forms (e.g., for @(see
 books)).</p>")
other
(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 @(see
 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 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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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 @(see 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>")
other
(defxdoc set-brr-evisc-tuple
  :parents (brr brr-evisc-tuple set-evisc-tuple)
  :short "Set the @(tsee brr-evisc-tuple)"
  :long "@({
  General Form:
  (set-brr-evisc-tuple ev state)
  })

 <p>where @('ev') is either the keyword @(':default') or a legal @(tsee
 evisc-tuple).  This function sets the evisceration tuple used by @(see
 brr-commands).  The current value can be retrieved with @(tsee
 brr-evisc-tuple).  The initial value is @(':default') which means the
 @(':term') evisceration tuple is used.  To see how the @('brr-evisc-tuple')
 is used see @(tsee brr-evisc-tuple).</p>

 <p>Think of @('brr-evisc-tuple') as a true global variable, not a locally
 bound variable of break-rewrite.  In particular, if you set the
 @('brr-evisc-tuple') inside a break-rewrite interactive break and eventually
 exit that break &mdash; either to enter a deeper break or return to a
 shallower break or to the ACL2 top-level &mdash; the @('brr-evisc-tuple') will
 retain its chronologically most recent setting.</p>

 <p>The general command for setting any of the system evisc-tuples is @(tsee
 set-evisc-tuple).</p>")
other
(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 @(see clause)s 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 @(see 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>")
other
(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') evaluates to a nonempty string that represents the desired
 directory (see @(see pathname)).  This command sets the connected book
 directory according to that string; see @(see cbd).  Thus, this command may
 determine which files are processed by @(tsee include-book), @(tsee
 certify-book), and @(tsee ld) @(see command)s, as well as by file operations
 such as @(tsee open-input-channel).</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>")
other
(defxdoc set-check-invariant-risk
  :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>")
other
(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 @(see
 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>")
other
(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 @(see 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>")
other
(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)
 })")
other
(defxdoc set-constraint-tracking
  :parents (encapsulate)
  :short "Generate markers to indicate origins of constraints"
  :long "@({
 General Form:
 (set-constraint-tracking flg)
 })

 <p>where @('flg') is Boolean.</p>

 <p>When @('flg') is @('t') the constraint subgoals generated by the
 @(':functional-instance') hint (see @(see hints) and @(see lemma-instance))
 have an additional hypothesis of the form @('(extra-info :constraint ...)')
 where the second argument to @('extra-info') is a quoted expression that
 indicates where the constraint came from.  Since @('extra-info') is a disabled
 defined function that always returns @('t'), the addition of this hypothesis
 does not change the meaning of the formula.</p>

 <p>Note: This is an event!  It does not print the usual event @(see 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>We expect this facility to be used only when a proof involving functional
 instantiation is failing and inspection of the subgoals or checkpoints leaves
 you asking the question ``why is it trying to prove this?''  But turning on
 this facility can cause a failing proof to fail even earlier because the
 @('extra-info') hypotheses may change the course of the proof.  We discuss
 some ways of handling this below.</p>

 <p>But first we give an example of the output that might be seen when the
 @('constraint-tracking') flag is set.  This example is intended
 to give you an idea of how to read the @('extra-info') &mdash; which of course
 is only visible if @(tsee gag-mode) is @('nil') or a checkpoint is printed.
 Because the ``quoted expression that indicates where the constraint came
 from'' is entirely informal, we do not give you a formal syntax and semantics
 for it.  Just study the examples.  Furthermore, as this facility matures we
 may well change the quoted expressions to be more informative.</p>

 <p>Recall the example use of @(':functional-instance') in @(see
 functional-instantiation-example).  (To understand what follows you really
 ought to read the example just cited.)  In particular, after we use @(tsee
 encapsulate) to constrain some functions and then prove a few useful lemmas,
 we prove the following by functional instantiation.  We include the entire
 un-gagged proof output below from a session in which the
 @('constraint-tracking') flag has been set.</p>

 @({
 ACL2 !>(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
                 (AC-FN *)
                 (AC-FN-ROOT (LAMBDA NIL 1))
                 (AC-FN-DOMAIN ACL2-NUMBERP)
                 (AC-FN-LIST TIMES-LIST)
                 (AC-FN-DOMAIN-LIST NUMBER-LISTP))))))

 [Note:  A hint was supplied for the goal above.  Thanks!]

 We augment the goal with the hypothesis provided by the :USE hint.
 The hypothesis can be derived from AC-FN-LIST-REV via functional in-
 stantiation, provided we can establish the seven constraints generated;
 the constraints can be simplified using the :executable-counterparts
 of IF and TAU-SYSTEM and the simple :rewrite rules ASSOCIATIVITY-OF-*
 and UNICITY-OF-1.  We are left with the following four subgoals.

 Subgoal 4
 (IMPLIES (EXTRA-INFO :CONSTRAINT '((DEFUN AC-FN-LIST)
                                    ((AC-FN BINARY-*)
                                     (AC-FN-LIST TIMES-LIST)
                                     (AC-FN-ROOT (LAMBDA NIL '1)))))
          (EQUAL (TIMES-LIST X)
                 (IF (ATOM X)
                     1
                   (* (CAR X) (TIMES-LIST (CDR X)))))).

 But simplification reduces this to T, using the :definitions ATOM and
 TIMES-LIST and primitive type reasoning.

 Subgoal 3
 (IMPLIES (AND (EXTRA-INFO :CONSTRAINT '((THEOREM AC-FN-ID)
                                         ((AC-FN BINARY-*)
                                          (AC-FN-DOMAIN ACL2-NUMBERP)
                                          (AC-FN-ROOT (LAMBDA NIL '1)))))
               (ACL2-NUMBERP X))
          (EQUAL (FIX X) X)).

 But simplification reduces this to T, using the :definition FIX and
 primitive type reasoning.

 Subgoal 2
 (IMPLIES (EXTRA-INFO :CONSTRAINT '((THEOREM AC-FN-COMM)
                                    ((AC-FN BINARY-*)
                                     (AC-FN-DOMAIN ACL2-NUMBERP)
                                     (AC-FN-ROOT (LAMBDA NIL '1)))))
          (EQUAL (* X Y) (* Y X))).

 But simplification reduces this to T, using primitive type reasoning
 and the :rewrite rule COMMUTATIVITY-OF-*.

 Subgoal 1
 (IMPLIES (EXTRA-INFO :CONSTRAINT '((DEFUN AC-FN-DOMAIN-LIST)
                                    ((AC-FN-DOMAIN ACL2-NUMBERP)
                                     (AC-FN-DOMAIN-LIST NUMBER-LISTP))))
          (EQUAL (NUMBER-LISTP X)
                 (COND ((ATOM X) T)
                       ((ACL2-NUMBERP (CAR X))
                        (NUMBER-LISTP (CDR X)))
                       (T NIL)))).

 But simplification reduces this to T, using the :definitions ATOM and
 NUMBER-LISTP and primitive type reasoning.

 Q.E.D.
 })

 <p>Note the @('EXTRA-INFO') hypotheses.  For example, in @('Subgoal 1'), just
 above, the hypothesis is</p>

 @({
 (EXTRA-INFO :CONSTRAINT '((DEFUN AC-FN-DOMAIN-LIST)
                           ((AC-FN-DOMAIN ACL2-NUMBERP)
                            (AC-FN-DOMAIN-LIST NUMBER-LISTP))))
 })

 <p>which indicates that @('Subgoal 1') is the functional instantiation
 of the defining equation for constrained function @('AC-FN-DOMAIN-LIST')
 under the functional substitution shown.  @('Subgoal 1') establishes that
 @('NUMBER-LISTP') satisfies the constraint on @('AC-FN-DOMAIN-LIST').</p>

 <p>You can view the definition of @('AC-FN-DOMAIN-LIST') with the
 @(':')@('pe') command.</p>

 <p>By inspecting the @('extra-info') in @('Subgoal 2'), above,</p>

 @({
 (EXTRA-INFO :CONSTRAINT '((THEOREM AC-FN-COMM)
                           ((AC-FN BINARY-*)
                            (AC-FN-DOMAIN ACL2-NUMBERP)
                            (AC-FN-ROOT (LAMBDA NIL '1)))))
 })

 <p>you should be able to recognize that it establishes that multiplication is
 commutative, which is required by the constraining @('THEOREM') named
 @('AC-FN-COMM'), since we are replacing @('AC-FN') by multiplication.  You can
 view the named theorem with the @(':')@('pe') command.</p>

 <p>You might occasionally see something like this</p>

 @({
 (EXTRA-INFO :CONSTRAINT '((:THEOREM <term>) <fn-substitution>))
 })

 <p>Note that this occurrence of the word ``THEOREM'' is as a keyword and what
 follows it is a term rather than a name.  This stems from the use of the
 @(':THEOREM') @(see lemma-instance) in the @(':functional-instance') hint.  In
 this case, the constraint is the term shown.</p>

 <p>The presence of these additional hypotheses may break some proofs that
 formerly worked!  For example, if @('constraint-tracking') is
 off, the events in the ACL2 Community Book
 @('/books/centaur/misc/tailrec.lisp') can be processed successfully.  But if
 the flag is on the proofs fails because the book is employing a very
 restrictive proof strategy designed to deal exactly with proving certain
 mechanically generated formulas and the @('extra-info') hypothesis makes the
 subgoals unrecognizable to that strategy.</p>

 <p>One way of dealing with this is to issue ``bye'' @(see hints), e.g., @(':by
 nil'), to subgoals that are failing before the one you want to see.
 Alternatively, you might use the @(':')@(tsee otf-flg) option to allow failing
 subgoals to be pushed so the prover can carry on to later subgoals.</p>

 <p>A third way to deal with this is to prove the rewrite rule</p>

 @({
 (defthm drop-extra-info-constraints
  (implies (equal x :constraint)
           (equal (extra-info x y) t))
  :hints (("Goal" :in-theory (enable extra-info))))
 })

 <p>which will cause the @('extra-info') hypotheses to rewrite to @('t') by the
 first simplification.  (Aside: The corresponding unconditional @(see rewrite)
 rule, @('(equal (extra-info :constraint y) t)'), is undesirable because it
 causes the @('extra-info') hypotheses to be simplified to @('t') before the
 goals are displayed to the user.)  So for example, if a
 @(':functional-instance') hint produced several immediate goals, one of which
 is @('Subgoal 3'), and the constraint tracking flag is set, then @('Subgoal
 3') will have an @('extra-info') hypothesis indicating the origin of that
 subgoal.  If the rewrite rule above is available, the @('extra-info') will
 have disappeared in the descendants of @('Subgoal 3').  So if you find
 yourself asking ``Where did this goal come from?''  you might refer back to
 the parent, @('Subgoal 3'), produced by the functional instance
 hint.  (Remember, descendant subgoals, e.g., @('Subgoal 3.17'''), have @(see
 clause-identifier)s that indicate their parentage, @('Subgoal 3').)</p>

 <p>That said, some proof strategies employed in the regression (including the
 one in the @('tailrec.lisp') book cited above) are so automatic and thus so
 tightly restricted that you may not find a way to get over the obstacles
 created by the @('extra-info') hypotheses!  However, of the thousands of books
 in the regression, as of Version 8.6, only three books fail to recertify when
 the constraint tracking flag is turned on, and one of those three succeeds if
 the rewrite rule above is included.  So we await further experience with this
 utility before investing more time in it.</p>")
other
(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 it may help to see :DOC raw-lisp-error.

    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>")
other
(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 @(see
 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 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>")
other
(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 @(see 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>")
other
(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>")
other
(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)
 })")
other
(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>")
other
(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>")
other
(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 @(see 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>")
other
(defxdoc set-duplicate-keys-action!
  :parents (output-controls)
  :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>")
other
(defxdoc set-dwp
  :parents (type-reasoning)
  :short "Affect the effort made in @(see type-reasoning)"
  :long "<p>This is a relatively advanced event that affects the @(see type-reasoning)
 heuristics.  (The name &ldquo;dwp&rdquo; stands for &ldquo;double-whammy
 property&rdquo; because the effect pertains to making a second attempt.)  The
 default behavior is obtained with @('(set-dwp nil)'), but type reasoning makes
 an extra effort after evaluation of @('(set-dwp t)').</p>

 <p>Note: This is an event!  It does not print the usual event @(see 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-dwp!) for a corresponding non-@(tsee local) event.</p>

 @({
  General Form:
  (set-dwp val)
 })

 <p>where @('val') is arbitrary but is typically @('t') or @('nil'), since
 every non-@('nil') value is treated the same as @('t').</p>

 <p>The following example, from Eric Smith, proves after evaluating @('(set-dwp
 t)') but otherwise fails.</p>

 @({
 (thm
  (implies (and (<= 0 (* 2 k)) ; extra hyp ;
                (unsigned-byte-p 4 k)
                (integerp x)
                (< x (+ 4 (* 2 k))))
           (<= x (+ 3 (* 2 k))))
  :hints (("Goal" :in-theory (disable unsigned-byte-p))))
 })

 <p>So why not always evaluate @('(set-dwp t)') at the beginning of an ACL2
 session?  Such a change added 3.9% to the certification of the ACL2 community
 books, and at least one book took almost twice as long to certify.  That isn't
 a huge penalty, but on the other hand it seems likely that @('(set-dwp t)') is
 helpful only in rare instances.</p>

 <p>To get the current value of @('dwp'), evaluate @('(get-dwp nil (w
 state))').</p>")
other
(defxdoc set-dwp!
  :parents (type-reasoning)
  :short "Affect the effort made in @(see type-reasoning), non-@(tsee local)ly"
  :long "<p>Please see @(see set-dwp), which is the same as @('set-dwp!')
 except that the latter is not @(tsee local) to the @(tsee encapsulate) or the
 book in which it occurs.  Probably @(see set-dwp) 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>")
other
(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 @(see 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 or
 the second pass of an @(tsee encapsulate) 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)))
 })")
other
(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,
 through 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)), as shown here:</p>

 @({
  ACL2 !>(set-evisc-tuple (evisc-tuple 3   ; print-level
                                       4   ; print-length
                                       nil ; alist
                                       nil ; hiding-cars
                                       )
                          :iprint t
                          :sites :all)

  ACL2 Observation in SET-EVISC-TUPLE:  Iprinting has been enabled.
   (:TERM :LD :TRACE :ABBREV . #@1#)
  ACL2 !>(without-evisc '(:TERM :LD :TRACE :ABBREV . #@1#))
  (:TERM :LD
         :TRACE :ABBREV
         :GAG-MODE :BRR)
  ACL2 !>
 })

 <p>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), and in response to @(see break-rewrite) commands.  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
 six 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>@(':BRR') &mdash; used for output from @(see brr-commands) issued in the
 @(see break-rewrite) loop.  When the value is @(':DEFAULT') then the
 <i>effective value</i> of this evisc-tuple is the @(':TERM') evisc-tuple with
 @('flg = t') (see above).  Also see @(see brr-evisc-tuple).</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>")
other
(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>")
other
(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>")
other
(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)').  ACL2 may also
 insert a linebreak (sometimes in an unaesthetic place) to prevent printing in
 a column that equals or exceeds the value of @('(@ fmt-hard-right-margin)').
 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>

 <p>Note that a right margin of 40 is used for pretty printing with @(tsee fmt)
 directives @('~y'), @('~Y'), @('~q'), and @('~Q') and can be changed to a
 positive integer @('N') with @('(set-ppr-flat-right-margin N state)').</p>")
other
(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>")
other
(defxdoc set-gag-mode
  :parents (output-controls)
  :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!).</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>")
other
(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>")
other
(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 &ldquo;@(see guard) checking on,&rdquo; 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 &ldquo;barring&rdquo; 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
 &ldquo;@(':')@(tsee program) mode&rdquo; with &ldquo;evaluation in Common
 Lisp&rdquo; and thus with &ldquo;@(see guard) checking on;&rdquo; and it is
 easy to confuse &ldquo;@(':')@(tsee logic) mode&rdquo; with &ldquo;evaluation
 in the logic&rdquo; and with &ldquo;@(see guard) checking off.&rdquo; 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
 &ldquo;Aside&rdquo; 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 &ldquo;guard-checking is on&rdquo; after
 @(':set-guard-checking') is invoked with values @('t'), @(':nowarn'), and
 @(':all'), otherwise (after value @('nil')) we say &ldquo;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 &ldquo;In the boot-strap
 world...&rdquo; 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 !>
 })")
other
(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>")
other
(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 @(see 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>")
other
(defxdoc set-in-theory-redundant-okp
  :parents (redundant-events)
  :short "Allow @(tsee in-theory) events to be redundant"
  :long "<p>See @(see redundant-events) for discussion of the notion of
 redundant events.</p>

 @({
  General Forms:
  (set-in-theory-redundant-okp nil) ; default
  (set-in-theory-redundant-okp t)   ; allow in-theory events to be redundant
 })

 <p>By default, @(tsee in-theory) events are never redundant.  This behavior
 avoids a redundancy check that could be a bit expensive, as it would require
 computing the current theory and checking its equality to the new theory.
 Evaluation of the event @('(set-in-theory-redundant-okp t)') enables that
 redundancy check, so that when an @('in-theory') event computes a theory that
 is equal to the current theory, then that event is redundant.</p>

 <p>To see the current setting (i.e., the default of @('nil') or else @('t')
 after evaluation of @('(set-in-theory-redundant-okp t)')), evaluate
 @('(get-in-theory-redundant-okp state)').</p>

 <p>Note: This is an event!  It does not print the usual event @(see 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>")
other
(defxdoc set-induction-depth-limit
  :parents (induction-depth-limit)
  :short "Set the @(see induction-depth-limit)"
  :long "@({
  Examples:
  (set-induction-depth-limit 3)   ;; Set the induction depth limit to 3.
  (set-induction-depth-limit nil) ;; Remove the induction depth limit.
 })

 <p>Note: This is an event!  It does not print the usual event @(see 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-induction-depth-limit!) for a corresponding non-@(tsee local)
 event.</p>

 @({
  General Form:
  (set-induction-depth-limit x)
 })

 <p>where @('x') evaluates to a value that is a natural number or @('nil').
 The induction-depth-limit is set to that value; see @(see
 induction-depth-limit).</p>")
other
(defxdoc set-induction-depth-limit!
  :parents (induction)
  :short "Set the induction-depth-limit non-@(tsee local)ly"
  :long "<p>Please see @(see set-induction-depth-limit), which is the same as
 @('set-induction-depth-limit!')  except that the latter is not @(tsee local)
 to the @(tsee encapsulate) or the book in which it occurs.  Probably @(tsee
 set-induction-depth-limit) 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>")
other
(defxdoc set-inhibit-er
  :parents (output-controls errors)
  :short "Control the error output"
  :long "@({
  Examples:
  (set-inhibit-er "translate" "failure")
 })

 <p>Note: This is an event!  It does not print the usual event @(see 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-er!) for a corresponding non-@(tsee local) event.
 Indeed, @('(set-inhibit-er ...)') is equivalent to @('(local
 (set-inhibit-er! ...))').</p>

 @({
  General Form:
  (set-inhibit-er string1 string2 ...)
 })

 <p>where each string is considered without regard to case.  This macro is is
 essentially @('(local (table inhibit-er-table nil 'alist :clear))'),
 where @('alist') pairs each supplied string with @('nil'): that is, @('alist')
 is @('(pairlis$ lst nil)') where @('lst') is the list of strings supplied.
 This macro is an event (see @(see table)), but no output results from a
 @('set-inhibit-er') event.</p>

 <p>ACL2 prints errors that are generally important to see.  This utility is
 appropriate for situations where one prefers not to see all error messages.
 Individual ``labeled'' error output can be silenced.  Consider for example</p>

 @({
  ACL2 Error [Failure] in ( DEFUN FOO ...):  See :DOC failure.
 })

 <p>Here, the label is "Failure".  The argument list for
 @('set-inhibit-er') is a list of such labels, each of which is a string.
 Any error message is suppressed if its label is a member of this list, where
 case is ignored.  Thus, for example, the error output above will be avoided
 after a call of @('set-inhibit-er') that contains the string,
 @('"Failure"') (or any string that is @(tsee string-equal) to
 @('"Failure"'), such as @('"failure"') or @('"FAILURE"')).  In summary:
 the effect of this event is to suppress any error output whose label is a
 member of the given argument list, where case is ignored.</p>

 <p>At this time, many error messages are printed without a label, for example
 (as of this writing) the following.</p>

 @({
 ACL2 !>(+ x 3)


 ACL2 Error in TOP-LEVEL:  Global variables, such as X, are not allowed.
 See :DOC ASSIGN and :DOC @.

 ACL2 !>
 })

 <p>These can only be suppressed by turning off all error output; see @(see
 set-inhibit-output-lst).  Feel free to ask the ACL2 implementors to add
 labels; for example, you might ask for a label in the example above (which
 could be @('"Globals"') or @('"Global-variables"')).</p>

 <p>Note that @('set-inhibit-er') has no effect on the value(s) returned by an
 expression (excepting the ACL2 @(see state) since it formally includes
 output).</p>

 <p>The list of currently inhibited error types is the list of keys in the
 @(see table) named @('inhibit-er-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-er-table (w state))').  Of
 course, if error output is inhibited overall &mdash; see @(see
 set-inhibit-output-lst) &mdash; then this value is entirely irrelevant.</p>

 <p>See @(tsee toggle-inhibit-er) for a way to add or remove a single
 string.</p>")
other
(defxdoc set-inhibit-er!
  :parents (output-controls errors)
  :short "Control error output non-@(tsee local)ly"
  :long "<p>Please see @(see set-inhibit-er), which is the same as
 @('set-inhibit-er!')  except that the latter is not @(tsee local) to the
 @(tsee encapsulate) or the book in which it occurs.  Probably @(see
 set-inhibit-er) 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>")
other
(defxdoc set-inhibit-output-lst
  :parents (output-controls)
  :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 x)
 })

 <p>where @('x') 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
    comment        output from cw, cw!, and utilities like time$ that use them
 })

 <p>It is possible to inhibit each kind of output by putting the corresponding
 name into @('x').  For example, if @(''warning') is included in (the value
 of) @('x'), 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) and @(see
 set-inhibit-er) for how to inhibit individual warning and error output
 types, respectively, and see @(see set-inhibited-summary-types) for how to
 inhibit individual parts of the @(see summary).</p>

 <p>Printing of events on behalf of @(tsee certify-book) and @(tsee
 encapsulate) is inhibited when both @(''event') and @(''prove') belong to the
 value of the input.  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>To get the current of names representing kinds of inhibit output, evaluate
 @('(@ inhibit-output-lst)').</p>

 <p><i>Note for advanced users.</i> By including @('warning!') in the value of
 the input, 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>")
other
(defxdoc set-inhibit-warnings
  :parents (output-controls)
  :short "Control warnings"
  :long "@({
  Examples:
  (set-inhibit-warnings "theory" "use")
 })

 <p>Note: This is an event!  It does not print the usual event @(see 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 is
 essentially @('(local (table inhibit-warnings-table nil 'alist :clear))'),
 where @('alist') pairs each supplied string with @('nil'): that is, @('alist')
 is @('(pairlis$ lst nil)') 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>

 <p>See @(tsee toggle-inhibit-warning) for a way to add or remove a single
 warning string.</p>")
other
(defxdoc set-inhibit-warnings!
  :parents (output-controls)
  :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>")
other
(defxdoc set-inhibited-summary-types
  :parents (output-controls)
  :short "Control which parts of the @(see 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*'), which is @(`*summary-types*`).
 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 @(see summary) will be printed.</p>

 <p>To control summary types for a single event, see @(see with-output).</p>")
other
(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>")
other
(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.  (See @(see break-rewrite) for
 more about the interaction of @('break-rewrite') with iprinting.)</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').
 Otherwise, if the next call of @('set-iprint') is with a first argument of
 @('t'), then iprint indices will start at the next available value rather than
 going back to 1.</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 it may help to see :DOC raw-lisp-error.

  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 it may help to see :DOC raw-lisp-error.

 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>")
other
(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 @(see 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>")
other
(defxdoc set-let*-abstractionp
  :parents (output-controls)
  :short "To shorten many prettyprinted @(see clause)s"
  :long "<p>Note: This is an event!  It does not print the usual event @(see
 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
 @(see 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>")
other
(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 @(see 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>")
other
(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>")
other
(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 @(see 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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(defxdoc set-persistent-whs-and-ephemeral-whs
  :parents (wormhole)
  :short "maintaining wormhole coherence"
  :long "@({
  General Form:
  (set-persistent-whs-and-ephemeral-whs name new-status state)
  })

  <p>where @('name') is the name of a @(tsee wormhole) other than one of the
  built-in ACL2 system wormholes, and @('new-status') is the desired status of
  the wormhole.  ACL2 insists that @('name') be supplied as a @(see quote)d
  constant.  The constant @('*protected-system-wormhole-names*') lists the
  names of the built-in wormholes and includes @('brr') (the @(see
  break-rewrite) wormhole name), @('accumulated-persistence'), and
  @('fc-wormhole') (the name of the wormhole managing @(see
  forward-chaining-reports)), among others.</p>

  <p>@('Set-persistent-whs-and-ephemeral-whs') moves @('new-status') into the
  wormhole's persistent-whs (the status stored outside of the ACL2 state) and
  then executes @(tsee sync-ephemeral-whs-with-persistent-whs) to re-establish
  coherence.  It returns a modified @('state').</p>

  <p>See @(see wormhole-programming-tips) for some tips for using this
  function.</p>")
other
(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>")
other
(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 base (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 !>
 })")
other
(defxdoc set-print-case
  :parents (io acl2-built-ins symbols)
  :short "Control whether @(see symbols) are printed in upper case or in lower case"
  :long "<p>By default, @(see 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 @('~x'), @('~X'), @('~y'), or @('~Y'), 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>")
other
(defxdoc set-print-clause-ids
  :parents (output-controls)
  :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-system print-clause-id-okp print-clause-id-okp-level-4)
 })")
other
(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))
 })
 ")
other
(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 !>
 })")
other
(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 @(see 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 @(see 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 @(see 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 !>
 })")
other
(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.  See @(see q).</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-on! ; same as above, but no trust tag required
  :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 @(see program) mode, but even further from @(see logic)
 mode).</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).  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 raw Lisp code may be useful, and where load time is much
 faster than the time required for a full-blown @(tsee include-book) &mdash;
 but not that 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) @(see with-raw-mode), @(see defttag), and @(see
 progn!).</p>

 <p>Below are several disadvantages to using 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 mostly
 unchanged for raw mode, even to the point of attempting appropriate printing
 for state and stobjs (though this is merely heuristic when the top-level
 function is defined in raw mode), for example as follows.</p>

 @({
 ACL2 !>(defstobj st fld)

 Summary
 Form:  ( DEFSTOBJ ST ...)
 Rules: NIL
 Time:  0.02 seconds (prove: 0.00, print: 0.00, other: 0.02)
  ST
 ACL2 !>(set-raw-mode-on!)

 TTAG NOTE: Adding ttag :RAW-MODE-HACK from the top level loop.
 ACL2 P>(defun f (st) st)
 F
 ACL2 P>(f st)
 <st>
 ACL2 P>(defun g (st state) (mv 3 st state))
 G
 ACL2 P>(g st state)
 (3 <st> <state>)
 ACL2 P>(defun h (state) (mv nil 17 state))
 H
 ACL2 P>(h state) ; notice the leading space; see below
  17
 ACL2 P>
 })

 <p>There is however one major exception.  If the value to be printed contains
 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, as
 indicated in the ``leading space'' comment above; see @(see
 ld-post-eval-print).  In particular, 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>Evaluation in raw mode attempts to maintain global @(see stobjs), but may
 not accommodate arbitrary raw Lisp hacks that hide the stobj returned by ACL2.
 This can happen in two cases: when array resizing is used on the
 unique (array) field of a stobj, and when @(tsee swap-stobjs) is used.
 Consider for example the following log.  Evaluation behaves nicely for all
 forms except the last, where resizing seems not to have taken effect as
 explained after the log, below.</p>

 @({
 ACL2 !>(defstobj st fld)

 Summary
 Form:  ( DEFSTOBJ ST ...)
 Rules: NIL
 Time:  0.02 seconds (prove: 0.00, print: 0.00, other: 0.02)
  ST
 ACL2 !>(defstobj st2 (ar :type (array t (8)) :resizable t))

 Summary
 Form:  ( DEFSTOBJ ST2 ...)
 Rules: NIL
 Time:  0.02 seconds (prove: 0.00, print: 0.00, other: 0.02)
  ST2
 ACL2 !>(set-raw-mode-on!)

 TTAG NOTE: Adding ttag :RAW-MODE-HACK from the top level loop.
 ACL2 P>(progn (update-fld 3 st) 17)
 17
 ACL2 P>(resize-ar 20 st2)
 <st2>
 ACL2 P>(ar-length st2)
 20
 ACL2 P>(progn (resize-ar 30 st2) 17)
 17
 ACL2 P>(ar-length st2) ; Should be 30, but it's not!
 20
 ACL2 P>
 })

 <p>The reason for the last form's ``wrong'' result (and the other ``correct''
 results) is technical.  A stobj with a single array field is exactly that
 array in raw Lisp (except in some cases where that may be an array of
 characters), in which case resizing completely replaces the stobj in the
 global structure that stores the global stobj values.  The use of raw-Lisp
 @('progn') hides the evidence of stobj modification, which is based on the
 stobjs returned by the form (but this @('progn') form returns 17).  Such
 evidence is available in the earlier call of @('resize-ar') above, since ACL2
 knows that @('resize-ar') returns a @('st2') stobj.  The @('update-fld') call
 does not provide such evidence for @('st1'), again because of the @('progn')
 around the call; but @('update-fld') actually modifies the stobj in place,
 rather than replacing it in the aforementioned global structure.</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>")
other
(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>")
other
(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>")
other
(defxdoc set-raw-proof-format
  :parents (output-controls)
  :short "Proof output with @(see rune)s as lists and maybe clausal goals"
  :long "@({
  General Forms:
  (set-raw-proof-format t)
  :set-raw-proof-format t
  (set-raw-proof-format nil)
  :set-raw-proof-format nil
  (set-raw-proof-format :clause)
  :set-raw-proof-format :clause

 })

 <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)).  The default behavior is obtained with argument
 @('nil').</p>

 <p>Calling this macro with argument @('t') 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>Calling this macro with argument @(':clause') provides not only the
 behavior described above for argument @('t'), but also causes goals to be
 printed using their internal clausal format: each goal is a list, implicitly
 disjoined, of translated @(see term)s.  See @(see clause).</p>

 <p>To obtain the current raw proof format value of @('t'), @(':clause') or
 @('nil'), corresponding to the descriptions above, evaluate @('(@
 raw-proof-format)').</p>")
other
(defxdoc set-raw-warning-format
  :parents (output-controls)
  :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>")
other
(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 @(see 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>")
other
(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 @(see
 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>")
other
(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
 its behavior to be modified or even disabled by changing the so-called
 <i>rw-cache-state</i>.  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>To obtain the current rw-cache-state, evaluate the form
 @('(rw-cache-state (w state))').</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 @(see 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>")
other
(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>")
other
(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>")
other
(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 (see @(see
 clause)).  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*').</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>")
other
(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>")
other
(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>")
other
(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 @(see
 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>")
other
(defxdoc set-subgoal-loop-limits
  :parents (miscellaneous)
  :short "Set the maximum length and repetition count of the subgoal path"
  :long "<p>The ACL2 ``waterfall'' (see @(see hints-and-the-waterfall)) produces
 a tree of Goals and Subgoals.  Consider a path through this tree in which each
 formula is an immediate descendant of the previous formula.  More precisely,
 each element of the path records a goal formula (represented as a @(see
 clause)), the name by which the user may refer to it, e.g., @('"Goal''"') or
 @('"Subgoal *1/2.3"') (represented as a @(see clause-identifier)), the
 clause processor that produced the formula, e.g., @('simplify-clause'),
 @('eliminate-destructors-clause'), @('fertilize-clause'), etc., and the @(see
 ttree) that records the @(see rune)s the processor used and other information
 about what the processor did.  Finally, each path starts with the top-level
 Goal or one of the cases produced by induction or a forcing round, and ends
 with (i) the reduction of the current goal to true, (ii) the abandonment of
 the proof attempt, or (iii) the addition of the current goal to the ``pool''
 for a subsequent attempt at an inductive proof.</p>

 <p>@('Subgoal-loop-limits') is a user-settable parameter that can limit (a)
 the maximum length of a path and (b) the maximum number of repetitions in the
 path of a formula and the clause processor that produced it.  In particular,
 @('subgoal-loop-limits') is a pair, @('(len . cnt)').  If @('len') is
 @('nil'), there is no limit on the length of a path, otherwise proof attempts
 are aborted if the length of any subgoal path exceeds @('len').  If @('cnt')
 is @('nil'), no check for formula repetition is made, otherwise each new
 subgoal formula (and its processor) is compared with @(tsee equal) to the
 ancestors along the path.  A probable loop is signaled and the proof is
 aborted if the number of occurrences exceeds @('cnt').</p>

 <p>The initial setting of @('subgoal-loop-limits') is @('(1000 . 2)').  That
 is, no proof can produce a path longer than a 1000 successive descendants or
 with more than 2 repetitions of the same formula (and processor).</p>

 <p>One might assume that a repetition count greater than 1 indicates a loop,
 but that is not true.  Various ACL2 clause processors may see the same formula
 at different points along a path and, guided by heuristics sensitive to what
 happened the last time the formula was seen, do something different.</p>

 <p>This function, @('set-subgoal-loop-limits'), sets the
 @('subgoal-loop-limits').</p>

 @({
 Example Forms:
 (set-subgoal-loop-limits nil) ; = (set-subgoal-loop-limits '(nil . nil))
 (set-subgoal-loop-limits t)   ; = (set-subgoal-loop-limits '(nil . 2))
 (set-subgoal-loop-limits 100) ; = (set-subgoal-loop-limits '(100 . 2))
 (set-subgoal-loop-limits :default) ; = (set-subgoal-loop-limits '(100 . 2))
 (set-subgoal-loop-limits '(100 . 5))

 General Form:
 (set-subgoal-loop-limits term)
 })

 <p>where @('term') should evaluate to a @(tsee cons) whose @(tsee car) is
 either @('nil') or a natural number and whose @(tsee cdr) is @('nil') or a
 non-0 natural number.  However, several abbreviations are allowed.</p>

 <ul>

 <li>If @('term') evaluates to @('nil'), then @('(nil . nil)') is used,
 imposing no limit on the length of a path and disabling loop detection.</li>

 <li>If @('term') evaluates to @('t'), then @('(nil . 3)') is used, imposing no
 length limit but defining a loop to be 3 or more repetitions of a formula and
 proof technique.</li>

 <li>If @('term') evaluates to a natural number, @('n'), then the pair
 constructed by @('(cons n 3)') is used, imposing a length limit of @('n') and
 defining a loop to be 3 or more repetitions of a formula and proof
 technique.</li>

 <li>If @('term') evaluates to @(':DEFAULT'), then the pair @('(1000 . 2)') is
 used, which sets the @('subgoal-loop-limits') to its initial value, imposing a
 maximum path length of 1000 and a maximum repetition count of 2.</li>

 </ul>

 <p>When these limits are violated, an error occurs and the proof attempt is
 abandoned.</p>

 <p>Of course, there are loops other than the simple ones this feature enables!
 For example, the available rules may cause the simplifier to transform a
 subgoal into a bigger one, e.g., @('Goal') @('(p x)') may be transformed to
 @('Goal'') @('(p (f x))'), which may then transform to @('Goal''') @('(p (f (f
 x)))'), etc.  <i>The prover does not check for such loops.</i> However, such
 loops are stopped by the path length limit.  (Internal rewrite loops, in which
 control never exits the simplifier, are not stopped even by a short path
 length.)  For other ways to restrict the prover, see @(see
 set-rewrite-stack-limit), @(see with-prover-time-limit), @(see
 with-prover-step-limit), @(see set-prover-step-limit), and @(see
 set-induction-depth-limit).</p>

 <p>If a proof aborts because of a probable loop and you suspect the prover is
 not really in a loop, i.e., that further iteration will break the cycle and
 make progress, use @('set-subgoal-loop-limits') to change the default 3 to a
 bigger number and try the proof again!</p>

 <p>Checking for simple loops will slow down the prover in proofs producing
 very long subgoal paths.</p>

 <p>Note: @('Set-subgoal-loop-limits') is an @(see event)!  It does not print
 the usual event @(see 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>To see the current limit</p>

 @({
 (subgoal-loop-limits (w state))
 })

 <p>When a loop is detected an error is signaled naming the clause processor,
 the repeated identical subgoals, and the runes used in each passage through
 the loop.  One such error message is shown below.</p>

 @({
 ACL2 Error [Waterfall-loop] in ( THM ...): The clause processor
 SIMPLIFY-CLAUSE has been applied to the same formula more than 2 times, namely
 at Goal', Goal'10' and Goal'19'.  That suggests a loop in the waterfall.
 Consequently, we are aborting!  The following list shows the runes used in
 each passage through the loop between successive subgoals.

 (("Goal'" ((:EXECUTABLE-COUNTERPART BINARY-+)
            (:REWRITE RULE1)
            (:REWRITE RULE2)
            (:REWRITE RULE3)
            (:REWRITE RULE4))
           "Goal'10'")
  ("Goal'10'" ((:EXECUTABLE-COUNTERPART BINARY-+)
               (:REWRITE RULE1)
               (:REWRITE RULE2)
               (:REWRITE RULE3)
               (:REWRITE RULE4))
              "Goal'19'")).

 For more information see :DOC set-subgoal-loop-limits.
 })

 <p>In the above example, we see that @('"Goal'"') was transformed by
 @('SIMPLIFY-CLAUSE'), using the runes listed, into @('"Goal'10'"').
 Furthermore, the formulas of @('"Goal'"') and @('"Goal'10'"') are
 identical.  We also see that @('SIMPLIFY-CLAUSE') then transformed
 @('"Goal'10'"'), using the same runes, to the same formula again at
 @('"Goal'19'"').</p>

 <p>After the error, and if you so choose, you can use the utility @(tsee pso)
 to display the (possibly gagged, see @(see set-gag-mode)) prover output
 between the named subgoals.</p>")
other
(defxdoc set-table-guard
  :parents (table events)
  :short "Set the @(':guard') for a @(see table)"
  :long "<p>This macro is a convenient interface for setting a @('table')'s
 guard to produce user-friendly error messages when the guard fails.  See @(see
 table) for background on table guards.  As noted there, the table guard may
 reference variables @('KEY'), @('VAL'), @('WORLD'), @('ENS'), and @('STATE');
 that is the case for the @('guard') and @('coda') mentioned below.  Also
 particularly relevant here is the fact that the table guard can return a
 single value, but it can also return @('(mv flg msg)'); in the latter case, if
 @('flg') is @('nil') then @('msg') is an error message.  @('Set-table-guard')
 is supplied a guard term that returns a single value, but sets the table guard
 to a corresponding term that returns values @('(mv flg msg')), where @('msg')
 is constructed to be user-friendly when it is non-@('nil').</p>

 @({
 General Form:
 (set-table-guard name guard
                  :topic topic
                  :show show
                  :coda coda)
 })

 <p>where @('name') is the name of a table, @('guard') is a term returning a
 single value that specifies the guard of that table, and the optional keyword
 arguments are as follows.</p>

 <ul>

 <li>@(':Topic') defaults to @('name').  Otherwise it is the name of a @(see
 documentation) topic to which the user is directed when the table guard
 fails.</li>

 <li>@(':Show') is @('nil') by default, in which case the guard term is not
 included in the error message; otherwise it is included.</li>

 <li>@(':Coda') is @('nil') by default.  Otherwise it should be a message (see
 @(see msgp)) to be printed, preceded by two spaces, after the message that
 would otherwise be printed.</li>

 </ul>

 <p>The error message when keywords are omitted is as shown in the example
 below, but (of course) where @('FOO'), @('MY-KEY'), and @('MY-VAL') are
 replaced respectively by the table name, the key, and the value.  We start our
 example by evaluating the following two events.</p>

 @({
 (defun foo-check (key val world)
   (declare (ignore val))
   (function-symbolp key world))
 (set-table-guard foo (foo-check key val world))
 })

 <p>Then evaluation of @('(table foo 'my-key 'my-val)') produces the following
 error message.</p>

 @({
 ACL2 Error in ( TABLE FOO ...):  The TABLE :guard for FOO disallows
 the combination of key MY-KEY and value MY-VAL.  See :DOC FOO.
 })

 <p>Here we show what happens to the error message if instead we set the table
 guard as follows.  As before, it should be clear from this example what the
 message would look like in general.  This time we evaluate:</p>

 @({
 (set-table-guard foo (foo-check key val world)
                  :topic set-foo
                  :show t
                  :coda (and (eq val 'my-val)
                             (msg "~x0 is an odd name for a value!"
                                  val)))
 })

 <p>This time, evaluation of @('(table foo 'my-key 'my-val)') produces an error
 message that references @(':DOC') topic
 @('SET-FOO') instead of @('FOO') (because of the @(':topic') argument), shows
 the table guard (because of the @(':show') argument), and prints a final coda
 (because of the @(':coda') argument).</p>

 @({
 ACL2 Error in ( TABLE FOO ...):  The TABLE :guard for FOO disallows
 the combination of key MY-KEY and value MY-VAL.  The :guard requires
 (FOO-CHECK KEY VAL WORLD).  See :DOC SET-FOO.  MY-VAL is an odd name
 for a value!
 })

 <p>It can be helpful for the table guard to be well-guarded.  For the examples
 above, the error message from @('(table foo 3 'my-val)') is ugly because
 @('3') fails to satisfy the guard of @('function-symbolp'), which is called by
 @('foo-check').  Here is a version of that function that produces the desired
 error message.</p>

 @({
 (defun foo-check (key val world)
   (declare (xargs :guard t)
            (ignore val))
   (and (symbolp key)        ; for guard of function-symbolp
        (plist-worldp world) ; for guard of function-symbolp
        (function-symbolp key world)))
 })

 <p>Finally, here are two examples from the ACL2 source code.  They illustrate
 that @(':show t') is reasonable when the table guard is concise, and that
 @(':topic') is necessary when the table name is undocumented.</p>

 @({
 (set-table-guard invisible-fns-table
                  (invisible-fns-entryp key val world)
                  :show t)

 (set-table-guard inhibit-warnings-table
                  (stringp key)
                  :topic set-inhibit-warnings)
 })")
other
(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>")
other
(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>")
other
(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)
 })")
other
(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>")
other
(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 :guard, type :stobjs, or :df present
  (set-verify-guards-eagerness 2) ; yes, unless :verify-guards nil
  (set-verify-guards-eagerness 3) ; yes
 })

 <p>Note: This is an event!  It does not print the usual event @(see 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'),
 @('2'), or @('3').  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'), @('2'), or @('3').  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.  It is also irrelevant to those @(tsee defun)
 @(see events) in which an explicit @(':')@(tsee verify-guards) setting is
 provided among the @(tsee xargs), except when the flag is @('3').  In the
 @(':')@(tsee program) mode case, @(see guard) verification is not done because
 it can only be done when logical functions are being defined.  Otherwise,
 unless the flag is @('3'), 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'), @(':stobjs'), or @(':dfs'),
 or there is a @(tsee type) declaration.  If the eagerness is @('2') or @('3'),
 @(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>")
other
(defxdoc set-warnings-as-errors
  :parents (warnings errors output-controls)
  :short "Changing @(see warnings) to hard @(see errors) (and vice-versa)"
  :long "<p>It is common for ACL2 users not to notice warnings.  That problem
 can be avoided by using the utility @('set-warnings-as-errors') to convert
 warnings to errors.  We start below with a general specification, followed by
 example forms, a detailed specification, and finally an extended example.</p>

 <h3>General Form</h3>

 <p>The general form is</p>

 @({
 (set-warnings-as-errors flg types state)
 })

 <p>where @('flg') is @('t'), @(':always'), or @('nil') and @('types') is
 either @(':all') or a list of strings.  The effect is to turn certain @(see
 warnings) into hard @(see errors), aborting the computation in progress.  Note
 that @('set-warnings-as-errors') is a function, so all arguments are
 evaluated.  Details are described in the section below entitled
 &ldquo;Detailed Specification&rdquo;.</p>

 <h3>Example Forms</h3>

 @({
 ; When a [Subsume] or [Use] warning is to be printed, cause a hard error
 ; instead with a similar message.
 (set-warnings-as-errors t '("Subsume" "Use") state)

 ; As above, but cause a hard error even if the warning is not to be printed,
 ; i.e., even if by default it would be suppressed as a warning because of
 ; prior use of set-inhibit-output-lst or set-inhibit-warnings.
 (set-warnings-as-errors :always '("Subsume" "Use") state)

 ; Restore the treatment of [Use] warnings as warnings.
 (set-warnings-as-errors nil '("Use") state)

 ; Treat a warning as a hard error, but only if the warning is to be printed
 ; (hence not suppressed by set-inhibit-output-lst or set-inhibit-warnings).
 (set-warnings-as-errors t :all state)

 ; Treat a warning as a hard error, whether the warning is printed or not.
 (set-warnings-as-errors :always :all state)

 ; Restore the default behavior, treating warnings as warnings, not errors.
 (set-warnings-as-errors nil :all state)
 })

 <h3>Detailed Specification</h3>

 <ul>

 <li>No warning whose type specified by constant
 @('*uninhibited-warning-summaries*') is converted to an error.  Those types
 are the ones that belong, with a case-insensitive check, to the list
 @(`*uninhibited-warning-summaries*`).  This exception overrides all discussion
 below.</li>

 <li>The behavior of @(see warnings) is affected for every warning type
 specified by the @('types') argument.  When its value is @(':all'), then all
 warnings are affected.  Otherwise the value of @('types') is a list of warning
 types (see @(see set-inhibit-warnings)): a true list of strings, each treated
 as case-insensitive.  Note that when the value is not @(':all'), the existing
 behavior for warning types is only changed for those in the value of
 @('types').</li>

 <li>When @('flg') is @(':always'), then every warning specified by @('types')
 is converted to a hard error, which aborts the evaluation in progress.  This
 happens even if the warning is suppressed (by @(tsee set-inhibit-output-lst)
 or @(tsee set-inhibit-warnings)).</li>

 <li>When @('flg') is @('t'), then when a warning specified by @('types') is to
 be printed, it is converted to a hard error, which aborts the evaluation in
 progress.  There is no error, however, if the warning is suppressed.</li>

 <li>When @('flg') is @('nil'), then every warning specified by @('types') is
 treated as a warning even if it had previously been treated as an error.</li>

 <li>When a warning of a given type (possibly @('nil') type) is converted to a
 hard error as specified above, then whether that error is printed is
 controlled by the usual mechanism for suppressing error messages; see @(see
 set-inhibit-er).  Note that the error will still be signaled regardless of
 whether the error message is thus suppressed.</li>

 <li>Previous evaluations of calls of @('set-warnings-as-errors') are ignored
 during @(tsee certify-book) and @(tsee include-book).  The handling of
 warnings as errors is restored at the end of these operations to what it was
 at the beginning.</li>

 </ul>

 <h3>Extended Example</h3>

 <p>ACL2 often prints @(see warnings), often with a message that includes a
 warning type.  Here is a contrived example.</p>

 @({
 (defthm foo t
  :hints (("Goal" :use car-cons))
  :rule-classes nil)
 })

 @({
 ACL2 Warning [Use] in ( DEFTHM FOO ...):  It is unusual to :USE the
 formula of an enabled :REWRITE or :DEFINITION rule, so you may want
 to consider disabling (:REWRITE CAR-CONS) in the hint provided for
 Goal.  See :DOC using-enabled-rules.
 })

 <p>In the example above, the warning type is the string, @('"Use'') which is
 treated as case-insensitive; see @(see set-inhibit-warnings).  But maybe we
 prefer that every such warning be converted to an error; after all, as the
 warning suggests, we might want to disable the used rule first.  It's easy to
 miss a warning but not an error, so we might do the following.</p>

 @({
 (set-warnings-as-errors t '("use") state)
 })

 <p>That modifies ACL2 behavior such that instead of the warning above, we get
 the following error (after using @(':u') to undo the effects of the
 @('defthm') event above).</p>

 @({
 HARD ACL2 ERROR [Use] in ( DEFTHM FOO ...):  It is unusual to :USE
 the formula of an enabled :REWRITE or :DEFINITION rule, so you may
 want to consider disabling (:REWRITE CAR-CONS) in the hint provided
 for Goal.  See :DOC using-enabled-rules.
 })

 <p>Note that this is a &ldquo;hard&rdquo; error: it aborts the computation in
 progress.</p>

 <p>Suppose however that we turn off the warning by evaluating either of the
 following two forms.</p>

 @({
 (set-inhibit-output-lst '(warning proof-tree))
 ; OR
 (set-inhibit-warnings "use")
 })

 <p>After evaluating either (or both) of these forms, the @('defthm') form
 above completes with no warnings or errors.  That's because there was no
 warning to print, and the @('flg') value of @('t') only has an effect for
 warnings that are printed.  If we want errors to occur even for warnings whose
 printing is suppressed, we should use the @('flg') value, @(':always').</p>

 @({
 (set-warnings-as-errors :always '("use") state)
 ; OR
 (set-warnings-as-errors :always :all state)
 })")
other
(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>")
other
(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>")
other
(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>")
other
(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)
 })")
other
(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 @(see 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>")
other
(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').  This function does not
 affect state or a wormhole's persistent-whs or ephemeral-whs.  It just returns
 a (possibly) new status object suitable as the value of the @('lambda')
 expressions in @(tsee wormhole-eval) and @(tsee wormhole).</p>")
other
(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').  This
 function does not affect state or a wormhole's persistent-whs or
 ephemeral-whs.  It just returns a (possibly) new status object suitable as the
 value of the @('lambda') expressions in @(tsee wormhole-eval) and @(tsee
 wormhole).</p>")
other
(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 @('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>")
other
(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 @(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$)")
other
(defxdoc seventh
  :parents (nth acl2-built-ins)
  :short "Seventh member of the list"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(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>")
other
(defxdoc sharp-d-reader
  :parents (reader numbers)
  :short "Read a rational number as a representable rational (see @(see df))"
  :long "<p>When the ACL2 reader encounters the two-character sequence @('#d'),
 it invokes the Lisp reader to obtain the next token, which should designate a
 Lisp double-precision floating-point number.  (Technically, the Lisp value of
 variable @('*read-default-float-format*') is the symbol @('DOUBLE-FLOAT') when
 the floating-point token is read.)  The reader then returns the rational
 number represented by that floating-point token.</p>

 <p>The discussion above is complete, but it may make more sense to those
 familiar with so-called <i>df</i> values in ACL2.  See @(see df).</p>

 <p>See also @(see sharp-f-reader), which reads input starting with @('#f').
 As with @('#d'), one reads floating-point notation and returns the
 corresponding rational number.  However, while @('#d') reads the next token as
 a Lisp floating-point number, @('#f') is specific to ACL2 and follows precise
 documented rules that, unlike @('#d'), allow use of underscores (@('_')) and
 hexadecimal notation.</p>")
other
(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>")
other
(defxdoc sharp-f-reader
  :parents (reader numbers)
  :short "Read a rational number in floating-point syntax"
  :long "<p>This topic is about reading expressions starting with @('#f').  See
 also @(see sharp-d-reader), which reads input starting with @('#d').  Both
 read a form of floating-point notation as a rational number.  However, while
 @('#d') reads the next token as a Lisp floating-point number, @('#f') is
 specific to ACL2 and follows rules documented explicitly below, including the
 use of underscores (@('_')) and hexadecimal notation.</p>

 @({
 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 !>
 })")
other
(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>")
other
(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>@(' y') &mdash; Print the object in full</p>

 <p>@(' n') &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 @('nil') if there is to be a query and otherwise is the
 answer to be used (without a query) for whether to print the input goal in
 full (@('t') for '@('y')', @('nil') for '@('n')', and @(':w') for '@('w')'),
 @('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>")
other
(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
 })")
other
(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>")
other
(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>")
other
(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 (see @(see stobj)), dfs
 (see @(see df)), and keyword values such as @(':guard').  When reading what
 follows below, all you need 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).  We also
 mention &ldquo;dfs&rdquo;, which are ACL2 expressions that denote Lisp
 floating-point values; see @(see df).  An expression that is neither a stobj
 name nor a df is said to be ``ordinary''.</p>

 @({
  Examples:
  ((hd *) => *)
  ((hd *) => * :formals (x) :guard (consp x))
  ((printer * state) => (mv * * state))
  ((mach * mach-state * state) => (mv * mach-state))
  ((df-mult3 :df :df :df) => :df)

  General Form:
  ((fn ...) => *)
  ((fn ...) => s) ; where s is a stobj name
  ((fn ...) => :df)
  or
  ((fn ...) => (mv x1 x2 ... xn)) ; where each xi is *, a stobj, or :df
  or for part1 and part2 as above,
  (part1 => part2 :kwd1 val1 ... :kwdn valn)
 })

 <p>where @('fn') is the constrained function symbol 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) the arguments and results
 that are stobjs or dfs.</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, or else that symbol must be
 @(':df') and the corresponding argument must be a df (see @(see df)).  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 ``*'', the keyword @(':df'), 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, a df, or a stobj.
 Otherwise, @('val') is of the form @('(mv y1 ... yk)'), where @('k') &gt; 1.
 Each @('yi') must be either the symbol ``*'', the keyword @(':df'), or the
 name of a stobj.  Such a @('val') indicates that @('fn') has multiplicity
 @('k') and the @('yi') indicate which results are ordinary, which are dfs, 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 generally @(':GUARD') and @(':FORMALS'), but see remarks at the end of
 this topic regarding @(':GLOBAL-STOBJS') and @(':TRANSPARENT') and, for
 ACL2(r), @(':CLASSICALP').  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 stobjs names or dfs.  Thus @(':STOBJS') and
 @9':DFS') are also legal keywords.  The form</p>

 @({
  (fn formals result ... :stobjs stobj-names :dfs df-names ...)
 })

 <p>specifies that @('stobj-names') is either the name of a stobj or else is a
 list of such names; also, both @('stobj-names') and @('df-names') are lists
 that must be contained in the @('formals') list.  Every name in
 @('stobj-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 additional keywords.
 The keyword @(':GLOBAL-STOBJS') specifies the use of the macro,
 @('with-global-stobj'), in attachments (see @(see defattach)); see @(tsee
 with-global-stobj) for explanation of this keyword.  The keyword
 @(':TRANSPARENT') specifies transparent functions; see @(see
 transparent-functions).  Finally, the keyword @(':CLASSICALP') is legal for
 ACL2(r) only (see @(see real)).  The value of this keyword must be @('t') (the
 default) or @('nil'), indicating respectively whether @('fn') is classical or
 not.</p>")
other
(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)")
other
(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)")
other
(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>")
other
(defxdoc sixth
  :parents (nth acl2-built-ins)
  :short "Sixth member of the list"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(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><b>WARNING</b>: The use of @('skip-proofs') carries an implicit promise by
 the user that the ensuing proof obligations are indeed theorems of the current
 theory.  When that is not the case, @('skip-proofs') can even allow
 inconsistent @(see events) to be admitted to the logic.  Use it at your own
 risk!  If your intention is truly to extend the current logical theory,
 consider using @(tsee defaxiom) instead.</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>")
other
(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)")
other
(defxdoc slow-alist-warning
  :parents (fast-alists)
  :short "Warnings/errors 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 message, which by default is followed by a Lisp break.  (The Lisp
 break may be ignored by continuing in the host Common Lisp, for example using
 @(':go') if the host Lisp is CCL.  Or, it may be aborted, often using @(':q'),
 again depending on the host Lisp.)</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 (again: an error from which you can continue) ensues.  For
 instance:</p>

 @({
   (set-slow-alist-action :break)    ; warn and also call break$ (default)
   (set-slow-alist-action :warning)  ; warn on slow access
   (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 (with a Lisp break, by default): discipline is
 ; violated because (@ a) no longer has a backing hash table.
 (assign b (hons-acons 'fn2 2 (@ a)))

 ; (C1) Fast alist warning/break: discipline is violated because (@ b) does not
 ; have a backing hash table.
 (assign c (hons-acons 'fn3 3 (@ b)))

 ; (C2) Fast alist warning/break: 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 a slow alist warning/break 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 the warning/break 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>")
other
(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>")
other
(defxdoc solution-to-acl2-quantifier-exercise-2
  :parents (quantifier-tutorial)
  :short "A solution to @(tsee quantifier-tutorial) Exercise 2"
  :long "<p> In @(see quantifier-tutorial) exercise 2, it asks if we can prove
  or disprove the conjecture below.</p>

  <blockquote><b>Exercise 2</b>. If there is an ACL2 object @('x') which
  satisfies @('M'), then there exists a least ACL2 object @('y') that satisfies
  @('M').</blockquote>

  <p>This hypothesis can be disproved. Here is one possible solution, provided
  by Yan Peng..</p>

  @({

  (in-package "ACL2")
  (include-book "misc/total-order" :dir :system)

  ;; This hypothesis can be disproved.
  ;; The intuition: find a function M that can be satisfied and does not have a
  ;; minimal object that satisfies it.

  ;; For example, if M is evenp, then for any ACL2 object that satisfies M, one
  ;; can always construct a smaller object by subtracting 2 from it, which also
  ;; satisfies M.

  ;; Instead of using defstub, we provide an implementation for M which calls
  ;; evenp.
  (defun M (x) (evenp x))

  ;; We prove a helper lemma that says if x satisfies M, then (- x 2) also
  ;; satisfies M and it is a smaller object.
  (defthm -2-satisfies-M-and-<<
    (implies (M x)
             (and (M (- x 2)) (<< (- x 2) x)))
    :hints (("Goal"
             :in-theory (enable << lexorder alphorder))))
  (in-theory (disable evenp M))

  (defun-sk some-M () (exists x (M x)))
  (in-theory (disable some-M some-M-suff))

  ;; We prove M can be satisfied by providing a witness 0.
  (defthm some-M-lemma
    (some-M)
    :hints (("Goal" :use ((:instance some-M-suff (x 0))))))

  ;; We negate none-below-2
  (defun-sk exists-below (y)
    (exists r (and (<< r y) (M r))))
  (in-theory (disable exists-below exists-below-suff))

  ;; We negate min-M2
  (defun-sk not-min-M () (forall y (implies (M y) (exists-below y))))
  (in-theory (disable not-min-M not-min-M-necc))

  ;; We prove that forall y, if y satisfies M, then there exists another smaller
  ;; object that satisfies M.
  (defthm not-min-M-lemma
    (not-min-M)
    :hints (("Goal"
             :use (;; The definition of not-min-M provides a witness
                   ;; (not-min-M-witness) that satisfies M but doesn't satisfy
                   ;; exists-below.
                   (:instance (:definition not-min-M))
                   ;; By instantiating exists-below-suff, we provide a smaller
                   ;; object r:(- (not-min-M-witness) 2) than
                   ;; y:(not-min-M-witness), and satisfies M. This makes
                   ;; (not-min-M-witness) vacuous, allowing us to prove the
                   ;; forall.
                   (:instance exists-below-suff
                              (r (- (not-min-M-witness) 2))
                              (y (not-min-M-witness)))))))

  ;; We prove both some-M and not-min-M
  (defthm |minimal does not exist|
    (and (some-M) (not-min-M)))

  })")
other
(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))))
 })")
other
(defxdoc soundness
  :parents (about-acl2)
  :short "Correctness property claimed for ACL2"
  :long "<p>What can we conclude when we use ACL2 to prove a formula or to
 compute the value of an expression?  This topic provides a high-level sketch
 of an answer.</p>

 <h3>Overview of the ACL2 logic</h3>

 <p>Any notion of correctness of ACL2 necessarily depends on the logic that it
 is intended to implement.  At its core, the ACL2 logic is just classical
 first-order logic.  The first-order theory for a given ACL2 session, which we
 may call the &ldquo;prover's theory&rdquo;, is the result of extending its set
 of built-in axioms according to @(see events) that have been executed in the
 session.</p>

 <ul>

 <li>The built-in axioms describe properties of the ACL2 data types, such as
 the following.

 @({
 ACL2 !>:pe car-cons
        -8139  (DEFAXIOM CAR-CONS
                 (EQUAL (CAR (CONS X Y)) X))
 ACL2 !>
 })</li>

 <li>A key extension principle is the Principle of Definition, which, for a
 definition @('(defun <fn> <args> <body>)'), introduces an axiom equating
 @('<body>') with application of @('<fn>') to @('<args>').  This principle
 permits recursion, and even @(see mutual-recursion), provided a suitable
 <i>measure conjecture</i> is provable.</li>

 <li>Other @(see events) come with extension principles too, including @(tsee
 encapsulate), @(tsee defchoose), @(tsee defpkg), and @(tsee include-book).
 Note that from a logical perspective, @(tsee defstobj) and @(tsee defabsstobj)
 just provide definitional extensions.</li>

 <li>Each ACL2 theory is <i>closed under induction</i>: that is, every instance
 of induction (in the language of the theory) below the ordinal @('epsilon-0')
 (see @(see ordinals)) is also in the theory.  In practical terms, this is what
 allows ACL2 to prove theorems by induction.</li>

 </ul>

 <p>For more about the ACL2 logic see the following publications by Matt
 Kaufmann and J Moore.</p>

 <ul>

 <li><a
 href='http://www.cs.utexas.edu/users/moore/publications/km97a.pdf'>&ldquo;A
 Precise Description of the ACL2 Logic&rdquo;</a> (April, 1998).</li>

 <li><a
 href='https://www.cs.utexas.edu/users/moore/publications/encap-story.pdf'>&ldquo;Structured
 Theory Development for a Mechanized Logic&rdquo;</a>, <i>Journal of Automated
 Reasoning</i> 26, no. 2 (2001) 161-203.</li>

 </ul>

 <h3>The soundness property for ACL2 sessions</h3>

 <p>The following soundness property is key for a given ACL2 session.</p>

 <blockquote>

 The theorem prover proves only formulas that are theorems in the corresponding
 prover's theory in that session.

 </blockquote>

 <p>Note that the theorem prover uses evaluation during proofs.  The soundness
 property thus encompasses the following: when such evaluation of a term
 @('tm') produces a value @('v'), then @('(equal tm 'v)') is provable from the
 context of that evaluation.  Evaluation in the top-level loop has such a
 property as well, but because of attachments (see @(see defattach)) and @(tsee
 apply$), provability is with respect to a larger &ldquo;evaluation
 theory&rdquo;; see @(see guarantees-of-the-top-level-loop).</p>

 <h3>Constraints on the soundness guarantee</h3>

 <p>Here is a list of constraints on the soundness guarantee.</p>

 <ul>

 <li>The prover's theory of a session is construed to include all axioms
 introduced by hidden @(see defpkg) events.  See @(see
 hidden-death-package).</li>

 <li>There is no soundness guarantee for a session in which there is raw Lisp
 evaluation with side effects.  (ACL2 normally avoids putting the user into raw
 Lisp, but this can happen with an interrupt, the use of @(tsee break$), or
 explicitly leaving the top-level loop with @(':')@(tsee q).)  &ldquo;Side
 effects&rdquo; should be interpreted as generously as possible: this certainly
 includes redefining a function or assigning to a variable, but not merely
 evaluating an arithmetic expression, for example.</li>

 <li>There is no soundness guarantee for a session in which any trust tag has
 been installed (see @(see defttag)).  The absence of trust tags is guaranteed
 by the absence of &ldquo;@('TTAG NOTE')&rdquo; being printed to standard
 output (that is, to @(tsee *standard-co*)).</li>

 <li>The soundness guarantee only applies when a set of books is certified from
 scratch, including @(see community-books), in a single environment &mdash; in
 particular, with the same Lisp implementation and operating system.  (In
 practice this is often not an issue.)</li>

 </ul>

 <h3>Examples of divergence among Lisp implementations</h3>

 <p>Next, we provide examples illustrating the last point above, restricting to
 the use of a single Lisp.</p>

 <p><b>Example 1: Divergences involving character and string
 operations.</b></p>

 <p>Consider the following log in raw Lisp using SBCL, which introduces
 versions of characters &ldquo;@('A')&rdquo; and &ldquo;@('a')&rdquo; that are
 augmented with an &ldquo;acute&rdquo; accent.</p>

 @({
 * (code-char 193)
 #LATIN_CAPITAL_LETTER_A_WITH_ACUTE
 * (code-char 225)
 #LATIN_SMALL_LETTER_A_WITH_ACUTE
 *
 })

 <p>While most Lisps that host ACL2 consider these two characters to be
 alphabetic characters with case (upper and lower, respectively), GCL does
 not (at least, a version available as of this writing).</p>

 @({
 (alpha-char-p (code-char 193)) ; T except NIL in GCL
 (alpha-char-p (code-char 225)) ; T except NIL in GCL
 (upper-case-p (code-char 193)) ; T except NIL in GCL
 (lower-case-p (code-char 225)) ; T except NIL in GCL
 (char-code (char-downcase (code-char 193))) ; 225 except 193 in GCL
 (char-code (char-upcase (code-char 225)))   ; 193 except 225 in GCL
 (let ((s (string-downcase (string (code-char 193)))))
   (char-code (char s 0)))      ; 225 except 193 in GCL
 (let ((s (string-upcase (string (code-char 225)))))
   (char-code (char s 0)))      ; 193 except 225 in GCL
 })

 <p><b>Example 2: Another divergence for @(tsee alpha-char-p).</b></p>

 @({
 ; True in SBCL 2.4.2, about the character it calls #MICRO_SIGN,
 ; but false in LispWorks 8.0.1:
 (alpha-char-p (code-char 181))

 ; False in SBCL 2.4.2, about the character it calls #CENT_SIGN,
 ; but true in Allegro CL 10.1:
 (alpha-char-p (code-char 162))
 })

 <p><b>Example 3: A divergence involving a floating-point computation.</b></p>

 <p>Here is another example illustrating the requirement on a single Lisp.  In
 ACL2 built on most host Lisp implementations, one can admit the following
 event.  (See @(see df) for background on floating-point computations with
 ACL2.)</p>

 @({
 (defthm usual-sin-2pi
   (equal (df-sin (df* 2 *df-pi*))
          #d-2.4492935982947064E-16))
 })

 <p>But in ACL2 built on LispWorks, one can instead admit the following.</p>

 @({
 (defthm lispworks-sin-2pi
   (equal (df-sin (df* 2 *df-pi*))
          #d-2.4492127076447545E-16))
 })

 <p>Clearly one could prove @('nil') by including two books, one containing
 each of these theorems.  (Aside: This does not violate the IEEE-754 spec,
 since it does not make specific requirements for trigonometric functions.)</p>

 <h3>Further reading for those interested in drilling down</h3>

 <p>This topic has discussed the soundness guarantee from the user perspective.
 Those interested in exploring deeper theoretical and implementation issues are
 welcome to read the extensive relevant comments in the ACL2 source code,
 including the comments labeled as follows (listed in order of appearance as of
 this writing, not to indicate the order in which to read them).</p>

 <ul>

 <li>Essay on Admitting a Model for Apply$ and the Functions that Use It</li>

 <li>Essay on Hidden Packages</li>

 <li>Essay on Soundness Threats</li>

 <li>Essay on a Total Order of the ACL2 Universe</li>

 <li>Essay on Illegal-states</li>

 <li>Essay on Evaluation in ACL2</li>

 <li>Essay on the Logical Basis for Linear Arithmetic</li>

 <li>Essay on the Correctness of Abstract Stobjs</li>

 <li>Essay on Memoization with Partial Functions (Memoize-partial)</li>

 <li>Essay on Correctness of Evaluation with Stobjs</li>

 <li>Essay on Correctness of Meta Reasoning</li>

 </ul>")
other
(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)))))))
 })")
other
(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>")
other
(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>")
other
(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 the use
 of @(tsee force) or @(tsee case-split).</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) rules involved in forcing (including case-splits; see @(see force)
 and see @(see case-split)).  For the example above we see the following
 output; and in fact, a hint to disable @('BAD') will avoid the specious
 simplification (although the proof will still fail).

 @({
 Splitter note (see :DOC splitter) for Goal (0 subgoals).
   case-split: ((:REWRITE BAD))
 })

 A more drastic possibility is to disable all forcing (including @(see
 case-split)s) and resubmit the formula to observe whether forcing is involved
 in the loop or not.  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>")
other
(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) @(See Summary)</p></blockquote>

 <p>Of course, (a) and (b) are skipped if proof output is inhibited, and (c) is
 skipped if @(see 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) @(See 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>")
other
(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>")
other
(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
 @('nil')-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)")
other
(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)")
other
(defxdoc standard-char-p+
  :parents (standard-char-p characters acl2-built-ins)
  :short "Recognizer for standard characters whose guard is @('t')"
  :long "<p>Logically @('standard-char-p+') is the same as @(tsee
 standard-char-p).  However, @('standard-char-p+') has a guard of @('t'), while
 @('standard-char-p') is guarded by @(tsee characterp).</p>

 @(def standard-char-p+)")
other
(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*).</p>")
other
(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*).</p>")
other
(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>")
other
(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>")
other
(defxdoc start-here
  :parents (acl2)
  :short "Introductory information about ACL2"
  :long "<p>This @(see documentation) topic provides a starting point for those
 who are new to ACL2 or want to learn more about it.  It accommodates different
 goals (ranging from mild curiosity about ACL2 to the desire to become an
 expert user) and different learning styles.  A quick scan should help you find
 a place to start that suits you.</p>

 <ul>

 <li><color rgb='#0090f0'>The <b>ACL2 home page</b></color>, at <tt><a
 href='http://www.cs.utexas.edu/users/moore/acl2/'>
 http://www.cs.utexas.edu/users/moore/acl2/</a></tt>, provides links that can
 take you to good places to start learning about ACL2.</li>

 <li>See @(see about-acl2) for <color rgb='#0090f0'><b>basic ``administrative''
 information</b></color> such as how to obtain and build ACL2, copyright and
 license material, mailing lists, connection with GitHub, and so on.</li>

 <li>See @(see using-acl2) for introductory material about <b>using</b>
 ACL2.</li>

 <li>See @(see tours) for <color rgb='#0090f0'><b>overviews at a high
 level</b></color>.  Also see the paper <i><a
 href='https://www.cs.utexas.edu/users/moore/publications/how-to-prove-thms/intro-to-acl2.pdf'>Industrial
 Proofs with ACL2</a></i>, which was written in the 1990s but is still useful
 for providing a brief overview of what can be done with ACL2.</li>

 <li><color rgb='#0090f0'><b>Tutorial Introductions</b></color> at various
 levels are available at the @(see acl2-tutorial) documentation topic and
 especially its subtopics.  (There is some overlap with the present
 topic.)</li>

 <li><color rgb='#0090f0'><b>Books</b></color> include the following.</li>

 <ul>

 <li><i><a
 href='http://www.cs.utexas.edu/users/moore/publications/acl2-books/car/index.html'>Computer-Aided
 Reasoning: An Approach</a></i> provides a detailed introduction to ACL2 and
 contains many exercises.</li>

 <li><i><a
 href='http://www.cs.utexas.edu/users/moore/publications/acl2-books/acs/index.html'>Computer-Aided
 Reasoning: ACL2 Case Studies</a></i> describes some relatively early
 applications of ACL2, including scripts as well as answers to the
 exercises.</li>

 </ul>

 <li>There are many <color rgb='#0090f0'><b>projects that use ACL2.</b></color>

 <ul>

 <li>See @(see interesting-applications) for an overview of some projects that
 have used ACL2.</li>

 <li>See @(see publications) for links to many books and papers.  You can also
 see @(see workshops) for programs, talks, and papers presented at the numerous
 ACL2 Workshops.</li>

 <li>The <a href='https://github.com/acl2/acl2/tree/master/books'>Community
 Books</a> is a repository of many projects, processed virtually continuously
 by virtue of constituting the ACL2 regression suite.  Many of those projects
 are descried in the <a
 href='https://acl2.org/doc/index.html'>ACL2+books
 online manual</a>.</li>

 </ul></li>

 <li><color rgb='#0090f0'><b>Programming with ACL2</b></color> is introduced
 gently in the documentation topic, @(see
 gentle-introduction-to-ACL2-programming).</li>

 <li><color rgb='#0090f0'><b>Logical basics</b></color> are presented in the
 @(see recursion-and-induction) documentation topic, for teaching yourself how
 to prove theorems about recursively defined functions using mathematical
 induction.  There are lots of exercises.  Some may find this a good way to get
 into ACL2, by understanding its proof system before attempting to use the
 tool.</li>

 <li><color rgb='#0090f0'><b>The theorem prover</b></color> is something
 perhaps best learned after studying the logical basics above, or at least
 giving them a quick glance.  Then you can just dive in or you can first study
 how to use it.

 <ul>

 <li>See @(see the-method) for concise guidance on the key technique for using
 the ACL2 prover effectively.</li>

 <li>See @(see introduction-to-the-theorem-prover) for a detailed discussion of
 how to be an effective user of the ACL2 theorem prover, including a focus on
 its primary proof technique, rewriting.</li>

 <li>The paper &ldquo;<a
 href='https://www.cs.utexas.edu/users/moore/publications/how-to-prove-thms/main.pdf'>How
 to Prove Theorems Formally</a> guides the reader towards effective use of
 ACL2, with exercises included.  Quoting the abstract: &ldquo;The real purpose
 of this paper is to answer the question how does one construct and manage
 large mechanically checked proofs (in ACL2)?&rdquo;.</li>

 </ul></li>

 <li>Here are some resources for trying out ACL2 without directly installing it
 yourself.</li>

 <ul>

 <li><see topic='@(url acl2-sedan)'>The ACL2 Sedan</see> is an <color
 rgb='#0090f0'><b>Eclipse-based plug-in that provides a modern development
 environment</b></color> and other capabilities that may be helpful for new
 ACL2 users.</li>

 <li>A basic <color rgb='#0090f0'><b>web-based interface to ACL2</b></color> is
 <a href='http://new.proofpad.org'>Proof Pad</a>.</li>

 <li>There is an <a href='https://hub.docker.com/r/atwalter/acl2'>ACL2 Docker
 container</a> (maintained at <a
 href='https://github.com/mister-walter/acl2-docker'>this repo</a>).</li>

 </ul>

 </ul>")
other
(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>")
other
(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>")
other
(defxdoc startup-banner
  :parents (interfacing-tools)
  :short "Modifying the ACL2 startup banner"
  :long "<p>When you start up an ACL2 executable built from sources obtained
  from GitHub between ACL2 releases, you'll typically see a startup banner like
  this:</p>

 @({
  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  + ACL2 Version 8.6+ (a development snapshot based on ACL2 Version 8.6) +
  +   built January 14, 2026  10:09:28.                                  +
  +   (Git commit hash: 1234567890abcdefghijklmnopqrstuvwxyz!@#$)        +
  + Copyright (C) 2026, Regents of the University of Texas.              +
  + ACL2 comes with ABSOLUTELY NO WARRANTY.  This is free software and   +
  + you are welcome to redistribute it under certain conditions.  For    +
  + details, see the LICENSE file distributed with ACL2.                 +
  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 })

 <p>The third line of that banner can be modified by setting environment
 variable @('ACL2_SNAPSHOT_INFO') to a non-empty string before saving the
 executable.  The value of that variable will be placed into the banner, for
 example as follows if that value is @('"This is my private
 executable."').</p>

 @({
 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 + ACL2 Version 8.6+ (a development snapshot based on ACL2 Version 8.6) +
 +   built January 14, 2026  09:56:49.                                  +
 +   (Note from the environment when this executable was saved:         +
 +    This is my private executable.)                                   +
 + Copyright (C) 2026, Regents of the University of Texas.              +
 + ACL2 comes with ABSOLUTELY NO WARRANTY.  This is free software and   +
 + you are welcome to redistribute it under certain conditions.  For    +
 + details, see the LICENSE file distributed with ACL2.                 +
 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 })

 <p>An exception is the special value, @('"none"'), which is treated as
 case-insensitive (so it can similarly be @('"None"'), @('"NONE"'), etc.).
 In that case, the third line of the original banner is omitted entirely.</p>")
other
(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 (except as a state
 value in a @(see multiple-value) return).  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>@('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>@('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>")
other
(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
 or macro such that @('(set-vari _ state)') returns @(tsee 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, the
 meaning of this form is to perform the following actions, in order.</p>

 <ol>

 <li>Set (in order) the global values of the indicated @(see state) global
 variables @('vari') to the values of @('formi').  Exception: This is skipped
 when @('vari') is a built-in state global and @('formi') is @('(f-get-global
 'vari state)').</li>

 <li>Execute @('body').</li>

 <li>Restore the @('vari') to their previous values.</li>

 <li>Return the @(see error-triple) produced by @('body'), where @(tsee state)
 reflects the modifications of the preceding step.</li>

 </ol>

 <p>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, we next discuss how the values
 are set and restored.  Let @('old-vali') be the value of state global variable
 @('vari') at the time @('vari') is about to be assigned the value of
 @('formi').  We say that a &ldquo;setter is supplied&rdquo; for @('vari') if
 @('set-vari') is supplied, either explicitly as in the General Form above, or
 implicitly by being associated with @('vari') in the value of the constant,
 @('*state-global-let*-untouchable-alist*')
 (whose definition appears at the end of this topic).  If no setter is supplied
 then @('vari') is set or restored to a value @('<val>') by evaluating
 @('(f-put-global 'vari <val> state)').  However, if a setter @('set-vari') is
 supplied, then the form evaluated will instead be @('(set-vari <val> state)').
 Having a setter supplied is particularly useful if @('vari') is @(see
 untouchable), since the call above of @(tsee f-put-global) is illegal.
 However, the use of @('*state-global-let*-untouchable-alist*') (mentioned
 above) avoids the need for supplying @('set-vari') explicitly for certain
 built-in @(see untouchable) state global variables, @('vari').</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 !>
 })

 <p>Finally, as promised above, here is the definition of the constant that
 maps certain built-in untouchable variables to setters.</p>

 @(def *state-global-let*-untouchable-alist*)")
other
(defxdoc stating-and-proving-lemmas-about-loop$s
  :parents (loop$)
  :short "Stating and proving theorems about @('loop$')s"
  :long "<p>In this topic we give some advice about how to state and prove
  theorems involving @('loop$')s, especially stating lemmas that are intended
  to rewrite @('loop$') statements and proving theorems about @('loop$')
  statements inductively.</p>

  <h3>Name @('Loop$')s When Memorable Names Come to Mind</h3>

  <p>Just because you can write iterative computations inline, don't get carried
  away!</p>

  <p>If you can think of a good name for the concept implemented by a
  @('loop$') statement, use @('defun') to define that name.  This is especially
  the case if you intend to reason about that @('loop$') statement or to write
  more than one instance of it.</p>

  <p>For example, rather than write instances of</p>

  @({
  (loop$ for a in x as b in y sum (* a b))
  })

  <p>it is better to define @('(dot-product x y)') with that @('loop$') as its
  body and then write calls of @('dot-product') and lemmas about
  @('dot-product') rather than that @('loop$').</p>

  <p>Basically, names are good as long as you can remember them.  They give you
  a place to hang lemmas and the lemmas match without you having to think about
  how lambda objects rewrite, local variables, etc.  Not all @('loop$')s
  compute concepts with obvious, memorable names, but just because you can
  write &ldquo;anonymous&rdquo; iterations doesn't mean you should!</p>

  <h3>Generalizing the Initial Values</h3>

  <p>Let's start with the most common issue raised by any inductive proof: the
  conjecture to be proved must be general enough to permit the provision of
  an appropriate inductive hypothesis.</p>

  <p>Consider how you would prove the conjecture below after defining @('rev')
  and @('rev1').</p>

  @({
  (defun rev (x)
    (if (endp x)
        nil
        (append (rev (cdr x)) (list (car x)))))

  (defun rev1 (x a)
    (if (endp x)
        a
        (rev1 (cdr x) (cons (car x) a))))

  (defthm rev1-is-rev
    (equal (rev1 x nil) (rev x)))
  })

  <p>The experienced ACL2 user would not attempt to prove @('rev1-is-rev') by induction
  because the @('nil') prevents the provision of an appropriate induction hypothesis.
  Instead, the user would first prove a generalization obtained by replacing that
  @('nil') by a variable and &ldquo;explaining&rdquo; the role of that variable on the
  right-hand side.</p>

  @({
  (defthm rev1-is-rev-generalized
    (equal (rev1 x a)
           (append (rev x) a)))
  })

  <p>The proof of the generalized theorem succeeds (though the prover must
  &ldquo;discover&rdquo; and then prove that @('append') is associative).</p>

  <p>With that theorem available, the proof of @('rev1-is-rev') is trivial,
  given that @('nil') is the right-identity for @('append') on true-lists and
  that @('rev') returns a true-list.</p>

  <p>Now consider defining reverse with a @('do') @('loop$').</p>

  @({
  (defun rev-loop$ (x)
    (loop$ with tail = x
           with a = nil
           do
           (if (endp tail)
               (return a)
              (progn (setq a (cons (car tail) a))
                      (setq tail (cdr tail))))))
  })

  <p>The experienced ACL2 user would not attempt to prove that @('(rev-loop$
  x)') is @('(rev x)') by induction!  The problem is the same as before: the
  @('nil') initialization of the iterative variable @('a') in the @('do')
  @('loop$') does not permit an appropriate inductive hypothesis.  Instead, the
  user needs to prove a more general theorem that cannot be stated in terms of
  @('rev-loop$') because that @('nil') is built into the definition.  We need
  to lift the @('loop$') out of the definition, generalize it, and prove a
  theorem about the generalized @('loop$').  Ideally we'd prove</p>

  @({
  (defthm rev-loop$-is-rev-generalized
    (equal (loop$ with tail = x
                  with a = a
                  do
                  (if (endp tail)
                      (return a)
                      (progn (setq a (cons (car tail) a))
                             (setq tail (cdr tail)))))
           (append (rev x) a))).
  })

  <p>ACL2's prover can derive induction schemes suggested by some @('loop$')
  statements, just as it can from some calls of recursive functions.  Because
  both iterative variables, @('tail') and @('a'), are initialized to variables,
  the @('DO') @('loop$') above suggests an appropriate induction.  But
  inductions for @('loop$')s raise some new issues as well as some traditional
  ones.</p>

  <p>ACL2 will prove the lemma above, if the associativity of @('append') has
  first been proved explicitly as a rewrite rule.  (The presence of the
  @('loop$') confuses the heuristics that enable the prover to
  &ldquo;discover&rdquo; the associativity of @('append').)</p>

  <p><b>Lesson 1</b>: If a @('loop$') has iterative variables initialized to
  non-variables, generalize them before expecting an induction to work!  If the
  @('loop$') is buried in a definition you'll have to lift the @('loop$') out
  of the definition to generalize it and prove a theorem about the generalized
  @('loop$').</p>

  <h3>Normal Forms in @('Loop$') Bodies</h3>

  <p>The lemma above, @('rev-loop$-is-rev-generalized'), is adequate to
  subsequently prove the main theorem,</p>

  @({
  (defthm rev-loop$-is-rev
    (equal (rev-loop$ x)
           (rev x))).
  })

  <p>But as stated, @('rev-loop$-is-rev-generalized') is fragile because
  it mentions the non-recursively defined function @('endp').  To explain this
  remark we need to walk through the proof of the main theorem.</p>

  <p>Recall that the prover always expands enabled functions that are not
  explicitly recursive.  And @('rev-loop$') is not explicitly recursive.  So
  the proof attempt of @('rev-loop$-is-rev') will expand the call of
  @('rev-loop$') and produce</p>

  @({
  Goal'
  (equal (loop$ with tail = x
                with a = nil
                do
                (if (endp tail)
                    (return a)
                    (progn (setq a (cons (car tail) a))
                           (setq tail (cdr tail)))))
         (rev x))
  })

  <p>If the @('loop$') term above is immediately rewritten, our generalized
  lemma would fire and reduce the goal to</p>

  @({
  Goal''
  (equal (append (rev x) nil)
         (rev x))
  })

  <p>and the proof would be completed as before with the right-identity
  rule.</p>

  <p>Indeed, this is what happens in this particular case, but the reason it
  works is completely unrelated to @('loop$')s!  Our generalized lemma has no
  hypotheses &mdash; it is an unconditional rewrite rule that is applied early
  in the &ldquo;preprocessing&rdquo; phase of simplification.</p>

  <p>Let's suppose the generalized lemma did have some hypotheses or otherwise
  failed to apply during preprocessing.  You can cause this to happen by
  restating the generalized lemma and the main theorem to have the (unnecessary
  but easily dealt with) hypothesis @('(true-listp x)').  The proof of the
  conditional generalized lemma still goes through, but the proof of the
  conditional main theorem fails because the generalized lemma never fires!</p>

  <p>The reason it never fires is that it is not tried during prepreprocessing
  (because preprocessing doesn't deal with conditional rules because
  preprocessing doesn't support backchaining) and @('Goal'') above enters the
  rewriter, which <i>rewrites every subterm of the term before trying to apply
  rules to the term itself</i>.  In particular, before the rewriter tries to
  apply our generalized rule it rewrites the subterms of the @('loop$')
  statement, including the body.  (Technically, it rewrites the @('lambda')
  object in the translation of the @('loop$').  See @(see
  rewrite-lambda-object).)</p>

  <p>This transforms</p>

  @({
  (loop$ with tail = x
         with a = nil
         do
         (if (endp tail)
             (return a)
             (progn (setq a (cons (car tail) a))
                    (setq tail (cdr tail)))))
  })

  <p>to</p>

  @({
  (loop$ with tail = x
         with a = nil
         do
         (if (consp tail)
             (progn (setq a (cons (car tail) a))
                    (setq tail (cdr tail)))
             (return a)))
  })

  <p>because @('(endp x)') expands to @('(not (consp x))') and the branches of
  the @('if') are swapped to eliminate the @('not').</p>

  <p>After this rewrite, our generalized lemma no longer matches.</p>

  <p><b>Lesson 2</b>: Do not prove rewrite rules that target @('loop$')
  statements containing terms in non-normal form!  That is, as with all other
  rewrite rules, make sure your target is normalized under your intended
  rewrite regime.</p>

  <p>So for example, in addition to watching out for non-recursive functions in
  the body, be alert for things like expressions that are rearranged by
  associativity and commutativity rules.  You wouldn't write a rewrite rule
  containing a subterm like @('(append (append a b) c)') if you're
  right-associating @('append') nests, nor would you include a subterm like
  @('(+ x 1)') if you're normalizing arithmetic expressions (in this case to
  @('(+ 1 x)')).  So don't use such non-normal terms in lemmas about
  @('loop$')s!</p>

  <p>The entire robust script for the @('rev-loop$') proof is given below.</p>

  @({
  (defun rev (x)
    (if (endp x)
        nil
        (append (rev (cdr x)) (list (car x)))))

  (defun rev-loop$ (x)
    (loop$ with tail = x
           with a = nil
           do
           (if (endp tail)
               (return a)
               (progn (setq a (cons (car tail) a))
                      (setq tail (cdr tail))))))

  (defthm assoc-of-append
    (equal (append (append a b) c)
           (append a (append b c))))

  (defthm rev-loop$-is-rev-generalized
    (equal (loop$ with tail = x
                  with a = a
                  do
                  (if (consp tail)
                      (progn (setq a (cons (car tail) a))
                             (setq tail (cdr tail)))
                      (return a)))
           (append (rev x) a)))

  (defthm rev-loop$-is-rev
    (equal (rev-loop$ x)
           (rev x)))
  })

  <p>The script is robust in the sense that even if you conditionalize the
  generalized lemma with a hypothesis that can be relieved in the main theorem
  the lemma will fire and rewrite the @('loop$') exposed when @('rev-loop$') is
  expanded.  Note that the @('loop$') was written with @('(endp tail)') in the
  @('defun') of @('rev-loop$') but lemma deals with the normalized form of that
  body.</p>

  <p>Here is another example, this one involving a @('do') loop without any
  @('WITH') clauses.  That in itself causes no special proof problems, but as
  noted in @(see do-loop$), it necessitates the use of a stobj in the body and
  that raises issues similar to those just mentioned.  So below we introduce a
  stobj, @('st'), with one field, @('fld').  We define @(tsee warrant)s for
  both @('fld') and @('update-fld'), and then we define a function,
  @('stobj-mem'), that uses a @('do') loop to determine whether a given element
  occurs in the field, simultaneously shortening the list in the field so that
  its @('car') is the element in question.  Here is the setup.</p>

  @({
  (defstobj st fld)
  (defwarrant fld)
  (defwarrant update-fld)

  (defun stobj-mem (e st)
    (declare (xargs :stobjs (st)
                    :guard (true-listp (fld st))))
    (loop$ do
           :values (st)
           :guard (and (stp st)
                       (true-listp (fld st)))
           :measure (acl2-count (fld st))
           (if (endp (fld st))
               (return st)
               (if (equal e (car (fld st)))
                   (return st)
                   (setq st (update-fld (cdr (fld st)) st))))))
  })

  <p>Note that there is no @('WITH') clause but the size of @('(fld st)') is
  decreasing.</p>

  <p>Suppose we want to prove that after running @('(stobj-mem e st)') on proper
  input, the final value of @('fld') is equal to @('(member e (fld st))').  The
  desired formal statement is</p>

  @({
  (defthm stobj-mem-correct
    (implies (and (stp st)
                  (true-listp (fld st))
                  (warrant fld update-fld))
             (let ((st1 (stobj-mem e st)))
               (and (stp st1)
                    (equal (fld st1)
                           (member e (fld st))))))
    :hints ...)
  })

  <p>Note that in the theorem we use @('st1') to denote the final value of the
  stobj whose initial value is @('st').  We have to provide the warrants for the
  accessor and updater used in the body of the @('loop$').</p>

  <p>This theorem is a little tricky to prove because we're proving a
  conjunction and after the @('(stobj-mem e st)') and the @('(stp st)') expand
  we get several conjectures, each of which requires induction.  It is simply
  easier to prove that the @('loop$') in @('stobj-mem') has the desired
  property and then use that lemma.  So we first prove:</p>

  @({
  (defthm stobj-mem-correct-lemma
    (implies (and (stp st)
                  (true-listp (fld st))
                  (warrant fld update-fld))
             (let ((st1 (loop$ do
                               :values (st)
                               :guard (and (stp st)
                                           (true-listp (fld st)))
                               :measure (acl2-count (fld st))
                               (if (consp (fld st))
                                   (if (equal e (car (fld st)))
                                       (return st)
                                       (setq st (update-fld (cdr (fld st)) st)))
                                   (return st)))))
               (and (stp st1)
                    (equal (fld st1)
                           (member e (fld st)))))))
  })

  <p>But note that we expanded the @('endp') in the statement of this lemma because
  @('endp') is built-in in a way that causes it often to expand even when disabled
  (as is actually noted in a warning message if we'd left the @('endp') in place).
  We also normalized the resulting @('(if (not (consp (fld st))) ...)') as explained
  in Lesson 2 above.</p>

  <p>Now we'd like to prove the desired theorem about @('stobj-mem'), expecting that
  function to expand and then the lemma to hit it and complete the proof.  But
  that won't work without a little more help!  The problem is that the lemma
  mentions @('stp'), @('fld'), and @('update-fld') in its left-hand side and those
  are non-recursively defined functions that will expand.  So to make the lemma
  match the rewritten main theorem we must disable those three functions.</p>

  @({
  (defthm stobj-mem-correct
    (implies (and (stp st)
                  (true-listp (fld st))
                  (warrant fld update-fld))
             (let ((st1 (stobj-mem e st)))
               (and (stp st1)
                    (equal (fld st1)
                           (member e (fld st))))))
    :hints (("Goal" :in-theory (disable stp fld update-fld))))
  })

  <h3>The Secret @('Setq') Problem</h3>

  <p>Another issue that comes up when posing lemmas about @('loop$')s is called
  the <i>secret @('setq') problem</i> and is best illustrated by example.</p>

  <p>Define the following function.</p>

  @({
  (defun secret-setq-problem (k x)
    (loop$ with x = x
           with j = 0
           do
           (cond ((endp x) (return 'bad))
                 ((equal j k) (return 'good))
                 (t (progn (setq x (cdr x))
                           (setq j (+ 1 j)))))))
  })

  <p>The function counts @('j') up from @('0') until it is equal to @('k'),
  while @('cdr')ing @('x').  It returns @('good') if @('j') reaches @('k')
  before the list is exhausted, and returns @('bad') otherwise.  Thus, this is
  a theorem.</p>

  @({
  (defthm secret-setq-problem-main
    (implies (and (natp k)
                  (< k (len x)))
             (equal (secret-setq-problem k x)
                    'good)))
  })

  <p>While @('secret-setq-problem-main') is provable by ACL2, it should be
  clear from Lessons 1 and 2 above that we first need to prove a lemma about
  the generalized, normalized loop$.  Here is a candidate lemma, which is
  proved by ACL2.</p>

  @({
  (defthm secret-setq-problem-lemma
    (implies (and (natp j)
                  (natp k)
                  (< k (+ j (len x)))
                  (<= j k))
             (equal (loop$ with x = x
                           with j = j
                           do
                           (if (consp x)
                               (if (equal j k)
                                   (return 'good)
                                   (progn (setq x (cdr x))
                                          (setq j (+ 1 j))))
                               (return 'bad)))
                    'good)))
  })

  <p>Following Lesson 1, we generalized the initial value of @('j'), which was
  @('0'), to @('j'), and we added the hypotheses that @('j') is a natural less
  than or equal to @('k').  We generalized the @('(< k (len x))') which we see
  in the main theorem to @('(< k (+ j (len x)))').  This accommodates the
  arbitrary initial @('j') and simplifies to @('(len x)') when @('j') is
  @('0').  Furthermore, as @('j') goes up and @('x') gets shorter, their sum
  stays fixed, which is necessary if the generalized hypothesis is going to
  survive induction.</p>

  <p>Following Lesson 2, we normalized the body.  We replaced the @('(endp x)')
  by @('(not (consp x))') and normalized the resulting @('IF') nest.</p>

  <p>The lemma is proved automatically by ACL2, using the induction suggested
  by the @('loop$').</p>

  <p>However, the attempt to prove the main theorem above will fail!  The lemma
  doesn't fire because the @('loop$') target still doesn't match.  (Note: we
  could forget about the lemma firing automatically.  Instead, we could give a
  @(':hint') that disables the lemma and @(':use')s the instance of it with
  @('j') replaced by @('0').  That succeeds.  But it is valuable for us to
  explore why it didn't work as a rewrite rule.)</p>

  <p>Sometimes to debug a failed proof it helps to compare the term that a
  lemma targets with its intended target in the checkpoint of the failed proof.
  This is especially true for @('loop$')s because their translations are so
  different from their outward appearance.  (See the sections titled
  &ldquo;Semantics&rdquo; in @(see for-loop$) and @(see do-loop$).)  The
  following use of the @(':')@(tsee pr) command shows our lemma's true form.
  It is the left-hand side, @('Lhs'), we are interested in because it is the
  target pattern of the rewrite rule.</p>

  @({
  ACL2 !>:pr secret-setq-problem-lemma

  Rune:    (:REWRITE SECRET-SETQ-PROBLEM-LEMMA)
  Enabled: T
  Hyps:    (AND (NATP J)
                (NATP K)
                (< K (+ J (LEN X)))
                (<= J K))
  Equiv:   EQUAL
  Lhs:     (DO$
            (LAMBDA$ (ALIST)
              (ACL2-COUNT (CDR (ASSOC-EQ-SAFE 'X ALIST))))
            (LIST (CONS 'X X)
                  (CONS 'J J)
                  (CONS 'K K))
            (LAMBDA$ (ALIST)
             (IF (CONSP (CDR (ASSOC-EQ-SAFE 'X ALIST)))
                 (IF (EQUAL (CDR (ASSOC-EQ-SAFE 'J ALIST))
                            (CDR (ASSOC-EQ-SAFE 'K ALIST)))
                     (LIST :RETURN 'GOOD
                           (LIST (CONS 'X (CDR (ASSOC-EQ-SAFE 'X ALIST)))
                                 (CONS 'J (CDR (ASSOC-EQ-SAFE 'J ALIST)))
                                 (CONS 'K (CDR (ASSOC-EQ-SAFE 'K ALIST)))))
                     (LIST NIL NIL
                           (LIST (CONS 'X (CDDR (ASSOC-EQ-SAFE 'X ALIST)))
                                 (CONS 'J (+ 1 (CDR (ASSOC-EQ-SAFE 'J ALIST))))
                                 (CONS 'K (CDR (ASSOC-EQ-SAFE 'K ALIST))))))
                 (LIST :RETURN 'BAD
                       (LIST (CONS 'X (CDR (ASSOC-EQ-SAFE 'X ALIST)))
                             (CONS 'J (CDR (ASSOC-EQ-SAFE 'J ALIST)))
                             (CONS 'K (CDR (ASSOC-EQ-SAFE 'K ALIST)))))))
              (LAMBDA$ (ALIST)
               (LIST NIL NIL
                    (LIST (CONS 'X (CDR (ASSOC-EQ-SAFE 'X ALIST)))
                          (CONS 'J (CDR (ASSOC-EQ-SAFE 'J ALIST)))
                          (CONS 'K (CDR (ASSOC-EQ-SAFE 'K ALIST))))))
              '(NIL) NIL)
  Rhs:     'GOOD
  Backchain-limit-lst: NIL
  Subclass: BACKCHAIN
  Loop-stopper: NIL
  })

  <p>The actual @('do$') term term you'll see in the checkpoint of the failed
  proof attempt is:</p>

  @({
  (DO$
   (LAMBDA$ (ALIST)
     (ACL2-COUNT (CDR (ASSOC-EQ-SAFE 'X ALIST))))
   (LIST (CONS 'X X)
         '(J . 0)
         (CONS 'K K))
   (LAMBDA$ (ALIST)
    (IF (CONSP (CDR (ASSOC-EQ-SAFE 'X ALIST)))
        (IF (EQUAL (CDR (ASSOC-EQ-SAFE 'J ALIST))
                   (CDR (ASSOC-EQ-SAFE 'K ALIST)))
            (LIST :RETURN 'GOOD
                  (LIST (CONS 'X (CDR (ASSOC-EQ-SAFE 'X ALIST)))
                        (CONS 'J (CDR (ASSOC-EQ-SAFE 'J ALIST)))
                        (CONS 'K (CDR (ASSOC-EQ-SAFE 'J ALIST)))))
            (LIST NIL NIL
                  (LIST (CONS 'X (CDDR (ASSOC-EQ-SAFE 'X ALIST)))
                        (CONS 'J (+ 1 (CDR (ASSOC-EQ-SAFE 'J ALIST))))
                        (CONS 'K (CDR (ASSOC-EQ-SAFE 'K ALIST))))))
        (LIST :RETURN 'BAD
              (LIST (CONS 'X (CDR (ASSOC-EQ-SAFE 'X ALIST)))
                    (CONS 'J (CDR (ASSOC-EQ-SAFE 'J ALIST)))
                    (CONS 'K (CDR (ASSOC-EQ-SAFE 'K ALIST)))))))
     (LAMBDA$ (ALIST)
      (LIST NIL NIL
           (LIST (CONS 'X (CDR (ASSOC-EQ-SAFE 'X ALIST)))
                 (CONS 'J (CDR (ASSOC-EQ-SAFE 'J ALIST)))
                 (CONS 'K (CDR (ASSOC-EQ-SAFE 'K ALIST))))))
     '(NIL) NIL)
  })

  <p>Note that the @('Lhs') matches the actual term, when @('J') is
  instantiated with @('0'), <i>except</i> in one place: the alist constructed
  in the @('(LIST :RETURN 'GOOD ...)') triple binds @(''K') to the value of
  @(''K') in @('Lhs') but binds @(''K') to the value of @(''J') in the actual
  term.  This happens because the actual term was rewritten under the
  assumption that the @('IF') test equating the value of @(''J') to the value
  of @(''K'), and the rewriter substituted the value of @(''J') for that of
  @(''K') because of term ordering.  The ACL2 pattern matching routine does
  not take account of tests.</p>

  <p>We could possibly fix this problem by changing how ACL2 stores lemmas or
  how the pattern matcher works.  But such changes could have far reaching
  consequences across the entire ACL2 regression suite, so we have made no such
  changes.</p>

  <p>Absent such changes, it's incumbent on the user to phrase the rewrite
  rule appropriately.  The question is, &ldquo;How can you make that particular
  @(''K') in @('Lhs') be @(''J')?&rdquo;</p>

  <p>One way would be to rephrase the rewrite rule by using the @('DO$') term
  from the checkpoint in place of the @('loop$') statement we wrote in
  @('secret-setq-problem-lemma').</p>

  <p>Another way to accomplish the same effect is to rewrite the @('loop$')
  statement as shown below.</p>

  @({
  (defthm secret-setq-problem-lemma
    (implies (and (natp j)
                  (natp k)
                  (< k (+ j (len x)))
                  (<= j k))
             (equal (loop$ with x = x
                           with j = j
                           with k = k                     ; ``new'' var
                           do
                           (if (consp x)
                               (if (equal j k)
                                   (progn (setq k j)      ; new setq!
                                          (return 'good))
                                   (progn (setq x (cdr x))
                                          (setq j (+ 1 j))))
                               (return 'bad)))
                    'good)))
  })

  <p>You can use @(':')@(tsee tcp) to confirm that the translation of the above
  @('loop$') matches the actual term in the checkpoint.</p>

  <p>Note that the inclusion of the new &ldquo;@('with k = k')&rdquo; does not
  add any new subterms to the translation, it merely allows assignment to a
  previously used but never assigned variable.  The order of the @('with')
  clauses determines the order of the alists being constructed, so pay
  attention to where @(''k') is bound in the alists.  Also note that the new
  @('setq') does not add any new subterms to the translation; it just affects the
  final value of @(''k') on that branch of the @('if') tree.  Finally note that
  we phrase the @('loop$') this way in the lemma <i>without changing how we
  write the @('loop$') in the @('defun').</i>  Writing the @('loop$') this way in
  the @('defun') would add an unnecessary @('setq') in the Common Lisp
  execution.  But there is no need to change how we write the @('loop$') in the
  defun.  This lemma matches what comes up when we prove things about the
  @('loop$') in the @('defun').</p>

  <p>Because this matching problem can repaired by adding an unnecessary @('setq')
  in the lemma, we call this the &ldquo;secret @('setq') problem.&rdquo;</p>

  <p><b>Lesson 3:</b> If the left-hand side of a rewrite rule contains an
  @('loop$') with an @('if') in the body, remember the secret @('setq')
  problem.  More practically, if a @('loop$') lemma you've proved fails to
  rewrite its target, compare the output of @(':')@('pr'), specifically the
  @('Lhs'), to the intended target printed in the checkpoint, and remember the
  secret @('setq') problem.</p>

  <h3>The Hidden Hypothesis Problem</h3>

  <p>Another issue you may occasionally confront when dealing with inductions
  suggested by @('do') @('loop$')s is indicated when the prover fails to prove
  the measure conjecture even though you &ldquo;know&rdquo; it is provable.
  To explain, we have to explain a little about how induction suggested by
  @('do') @('loop$')s are done.</p>

  <p>From every @('do') @('loop$') we can derive a proposed recursive function
  definition.  When the prover sees a @('do') @('loop$') in a conjecture that
  it has decided requires inductions, it generates that derived function, does
  an induction analysis for it, and adds any suggestions it gets to the set of
  candidate inductions to consider.  However, the derived function may not
  terminate &ldquo;normally.&rdquo; Recall that @(tsee do$) checks that the
  measure goes down before each iteration and returns a default value if that
  check fails.  Thus, to justify the induction suggested by the generated
  function the proof obligations include those that establish that the measure
  decreases <i>under the tests leading to further iterations in the @('loop$')
  body</i>.</p>

  <p>Those tests are not always sufficient to guarantee termination!  If the
  @('loop$') came from a guard verified function definition, termination was
  proved.  But it was proved as part of guard verification.  Remember the main
  purpose of guards in @('loop$')s: to allow us to execute the @('loop$') as a
  Common Lisp @('loop').  But that execution only happens when we know guards
  hold.  But @('loop$')s seen by the prover may not come from guard verified
  statements and, besides, guards are stripped out of conjectures to be proved
  because they're irrelevant to the logical meaning.</p>

  <p>However, it is logically valid to condition the induction-time measure
  conjectures on hypotheses from the conjecture being proved &mdash; and it is
  often ineffective to include all of those hypotheses.  So ACL2's induction
  mechanism chooses some of the available hypotheses and may not choose enough.
  This is the &ldquo;hidden hypothesis problem.&rdquo;  An example is below.</p>

  <p>The following function can be admitted and guard verified, meaning the
  termination obligation is proved as part of guard verification.</p>

  @({
  (defun hidden-hyp-problem (lo j)
    (declare (xargs :guard (and (natp lo) (natp j) (<= lo j))))
    (loop$ with j = j
           do
           :guard (and (natp lo) (natp j) (<= lo j))
           (if (equal lo j)
               (return 'good)
               (setq j (- j 1)))))
  })

  <p>Since since @('lo') and @('j') are both natural numbers and @('j')
  is (weakly) above @('lo') and is decremented on iteration, @('j') will
  eventually reach @('lo') and the @('loop$') will stop.</p>

  <p>The derived recursive function corresponding to this @('loop$'), which
  we'll call @('derived-fn') here, is</p>

  @({
  (defun derived-fn (lo j)
    (if (equal lo j)
        'good
        (derived-fn lo (- j 1)))).
  })

  <p>That derived function doesn't necessarily terminate.</p>

  <p>Now let's try to prove that the @('loop$') always returns @(''good').
  Note that it doesn't matter if we include guards in the conjecture or not.
  They're logically irrelevant and will be eliminated.</p>

  <p>However, the following proof attempt fails.  The prover chooses to induct
  as suggested by the @('do') @('loop$').  The induction scheme selected is
  shown.</p>

  @({
  ACL2 !>(defthm hidden-hyp-problem-main
           (implies (and (natp lo)
                         (natp j)
                         (<= lo j))
                    (equal (loop$ with j = j
                                  do
                                  :guard (and (natp lo) (natp j) (<= lo j))
                                  (if (equal lo j)
                                      (return 'good)
                                      (setq j (- j 1))))
                           'good)))

  ...

  This suggestion was produced using the :induction rule DO$.  If we
  let (:P J LO) denote *1 above then the induction scheme we'll use is
  (AND (IMPLIES (AND (NOT (EQUAL LO J))
                     (:P (+ -1 J) LO)
                     (INTEGERP J)
                     (<= 0 J))
                (:P J LO))
       (IMPLIES (AND (NOT (EQUAL LO J))
                     (< (+ -1 J) 0)
                     (INTEGERP J)
                     (<= 0 J))
                (:P J LO))
       (IMPLIES (AND (NOT (EQUAL LO J))
                     (NOT (INTEGERP (+ -1 J)))
                     (INTEGERP J)
                     (<= 0 J))
                (:P J LO))
       (IMPLIES (AND (EQUAL LO J) (INTEGERP J) (<= 0 J))
                (:P J LO))
       (IMPLIES (AND (INTEGERP J)
                     (<= 0 J)
                     (NOT (EQUAL LO J)))
                (L< (LEX-FIX (ACL2-COUNT (+ -1 J)))
                    (LEX-FIX (ACL2-COUNT J))))).
  Note that one or more measure conjectures included in the scheme above
  justify this induction if they are provable.  When applied to the goal
  at hand the above induction scheme produces six nontautological subgoals.

  ...
  })

  <p>The first four proof obligations, which are all proved by the prover,
  implicitly include the hypotheses that @('LO') is a natural below @('J')
  because they're hypotheses in the four conclusions, @('(:P J LO)').  But the
  last proof obligation has no hypotheses about @('LO') other than the test in
  the body of the @('loop$'), @('(NOT (EQUAL LO J))').  This proof obligation
  is not a theorem and the proof attempt will fail.</p>

  <p>If the prover had just generated the measure conjecture from the
  @('derived-fn') the last proof obligation would be even more inadequate!</p>

  @({
  (IMPLIES (NOT (EQUAL LO J))
           (L< (LEX-FIX (ACL2-COUNT (+ -1 J)))
               (LEX-FIX (ACL2-COUNT J)))).
  })

  <p>But we see that the prover actually augmented the hypothesis from the body
  with two literals it assumed were relevant from the conjecture being proved,
  namely @('(INTEGERP J)') and @('(<= 0 J)').  (The legality of such
  augmentation is illustrated by the book
  @('projects/apply/justification-of-do-induction.lisp').)  However, it did not
  include any facts about @('LO') other than the test in the @('loop$') body.
  This is a manifestation of the hidden hypothesis problem.  In this case, we
  wish it had included @('(NATP LO)') and @('(<= LO J)').  (One can regard this
  as a heuristic inadequacy, but enlarging the set of hypotheses can cause
  proofs to fail and we've been conservative in our heuristics for augmenting
  @('do') @('loop$') inductions.)</p>

  <p>You can fix this by providing an @(':induct') hint.  The @('loop$')
  statement in the hint below is exactly the @('loop$') statement in the
  theorem except we've added the UPPERCASE text.  This proof succeeds.</p>


  @({
  (defthm hidden-hyp-problem-main
    (implies (and (natp lo)
                  (natp j)
                  (<= lo j))
             (equal (loop$ with j = j
                           do
                           (if (equal lo j)
                               (return 'good)
                               (setq j (- j 1))))
                    'good))
    :hints (("Goal"
             :induct
             (loop$ with j = j
                    do
                    (IF (AND (NATP LO) (<= LO J))
                        (if (equal lo j)
                            (return 'good)
                            (setq j (- j 1)))
                        (RETURN 'IRRELEVANT-BASE-CASE))))))
  })

  <p><b>Lesson 4</b>: You can use @('loop$') to provide induction hints and
  those @('loop$')s don't have to be identical to ones in your goal theorem.
  In particular, your hint @('loop$') might contain more case analysis than
  the @('loop$')s in your conjecture.  You can use this fact to overcome the
  hidden hypothesis problem.</p>

  <p>Note that the derived function from the @('loop$') in the hint doesn't
  necessarily terminate either (because no mention is made that @('J') is a
  natural).  But the induction-time proof obligation is provable because it is
  still augmented by @('(INTEGERP J)') and @('(<= 0 J)') as before.</p>

  <h3>Avoiding Some Specially Defined Hint Functions</h3>

  <p>Another lesson suggested by the example above is that you don't always
  have to define a recursive function to suggest certain inductions.  Here is
  an example.  Recall the function @('rev1') from the beginning of this topic.
  Now define the functions that &ldquo;mark&rdquo; every element of a list and
  that check that every element is &ldquo;marked&rdquo;.</p>

  @({
  (defun mark-all (x)
    (if (consp x)
        (cons (list 'mark (car x))
              (mark-all (cdr x)))
        nil))

  (defun all-markedp (x)
    (if (consp x)
        (and (consp (car x))
             (eq (car (car x)) 'mark)
             (all-markedp (cdr x)))
        t)).
  })

  <p>Now prove</p>

  @({
  (thm (implies (all-markedp a)
                (all-markedp (rev1 (mark-all x) a))))
  })

  <p>No induction suggested by the functions in this theorem is appropriate.
  The appropriate induction assumes the theorem for @('x') replaced by @('(cdr
  x)') and @('a') replaced by @('(cons (list 'mark (car x)) a)').  (This is an
  example of rippling as discussed by Bundy, Basin, Hutter and Ireland, in the
  book <i>Rippling: Meta-Level Guidance for Mathematical Reasoning</i>,
  Cambridge University, UK, 2005.  But ACL2's induction heuristics don't
  implement rippling.)  We could, of course, define a recursive function that
  suggests the appropriate induction and provide it as a hint.  But in this case
  we needn't define a new function.  We can just use a @('loop$').</p>

  @({
  (thm (implies (all-markedp a)
                (all-markedp (rev1 (mark-all x) a)))
       :hints (("Goal" :induct
                (loop$ with x = x
                       with a = a
                       do
                       (if (consp x)
                           (progn (setq a (cons (list 'mark (car x)) a))
                                  (setq x (cdr x)))
                           (return 'base-case)))))).
  })

  <h3>Other Relevant :DOC Topics</h3>

  <p>See @(see lp-section-11) of the @('Loop$') Primer for a narrative of how
  we might solve a certain computational problem with a nest of two @('FOR')
  @('loop$').  We also show how we verify the guards and then prove that the
  @('loop$') solution is equivalent to a recursive solution.  In
  @(see lp-section-12) of the primer you'll find some exercises in
  proving theorems about @('FOR') @('Loop$')s
  (with answers in a Community Book).  In @(see lp-section-16) you'll find a
  narrative of how we might go about proving a theorem about a @('DO')
  @('Loop$').  And in @(see lp-section-17) you'll find exercises in proving
  theorems about @('DO') @('Loop$')s (with answers in a Community Book).</p>")
other
(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>This topic introduces the notion of a ``stobj'', or single-threaded object.
 It concludes with a link to a tour that introduces the use of stobjs by way of
 examples.  We recommend that you follow that link the first time you read
 about stobjs.  Detailed reference documentation about stobjs may be found in
 the subtopics listed at the end below; in particular 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 at the end of this topic for some relaxations).</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') that is declared as a
 stobj, 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))').  And instead of @('(MV X (LET ((ST (UPDATE-FIELD1 3 ST))) (FOO
 ST)))') write @('(LET ((ST (UPDATE-FIELD1 3 ST))) (MV X 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, and a
 @(':non-executable') keyword can be used to defer or totally avoid creating a
 &ldquo;global&rdquo; stobj for the given stobj name.</p>

 <p>But we are getting ahead of ourselves.  To start the stobj tour recommended
 earlier in this topic, see @(see stobj-example-1).</p>")
other
(defxdoc stobj-attachment-restrictions
  :parents (ld)
  :short "Restrictions on attachments to supporters of @(see stobj) primitives"
  :long "<p>This topic assumes that the reader is familiar with the basics of
 @(tsee defattach) and @(see stobj)s (which are introduced by @(tsee defstobj)
 and @(tsee defabsstobj)).  It concerns restrictions that disallow the use of
 @(tsee defattach) on <i>supporters</i> of @(see stobj) recognizers and, for
 @(tsee defabsstobj), other stobj primitives that return the new stobj.  Here,
 a <i>supporter</i> of a function symbol @('f') is a function symbol used in
 the event that introduces @('f') or, recursively, is a supporter of any of
 those function symbols.</p>

 <p>The @(see community-book)
 @('books/system/tests/stobj-attach-unsoundness.lisp'), developed by Sol
 Swords, illustrates a soundness bug that existed through ACL2 Version_8.6.
 That book shows several ways that @('nil') could be proved by using @(tsee
 defattach) to falsify stobj invariants &mdash; either the recognizer or, for
 abstract stobjs, the correspondence function.</p>

 <p>Those proofs of @('nil') no longer succeed because of the following two
 restrictions now imposed by ACL2.</p>

 <ol>

 <li>No supporter of a stobj recognizer is allowed to have an attachment.</li>

 <li>For a @(tsee defabsstobj) event, there must be a correspondence function
 whose supporters are not allowed to have attachments.</li>

 </ol>

 <p>The second of these criteria may be met by the @('defabsstobj') event in
 <i>either</i> of the following two ways.</p>

 <blockquote>

 <p>Keyword @(':CORR-FN-EXISTS') has value @('t'), and the value of
 @(':CORR-FN') is a function symbol whose supporters are not allowed to have
 attachments.</p>

 <p><b>OR</b></p>

 <p>Keyword @(':CORR-FN-EXISTS') has value @('nil') (the default), and the
 supporters of any stobj primitive (the creator and exports, in addition to the
 recognizer) that returns the new stobj are not allowed to have
 attachments.</p>

 </blockquote>

 <p>Note that in the first sub-case, where keyword argument
 @(':CORR-FN-EXISTS') has value @('t'), the definition of the @(':CORR-FN')
 symbol must be non-@(see local).  In the second sub-case, where keyword
 argument @(':CORR-FN-EXISTS') has value @('nil'), the notion of
 &ldquo;supporter&rdquo; of a stobj primitive is understood to include any
 function symbol that is a supporter of either the @(':LOGIC') or the
 @(':EXEC') function of that stobj primitive.</p>

 <p>We conclude with an optional remark (for those interested in theory) that
 discusses how the two sub-cases above are related.  Namely, for an abstract
 stobj @('st'), there is always an implicit correspondence function definable
 in terms of the primitives as follows.  A concrete state @('c_k') and abstract
 state @('a_k') correspond if there are corresponding sequences of values
 @('c_i') and @('a_i') (i &le; k) produced by corresponding applications of
 primitives, each of which returns the new stobj, as follows.</p>

 <ul>

 <li>@('c_0') and @('a_0') are the initial concrete (foundational) and abstract
 copies of @('st'), that is, produced by applying the @(':EXEC') and
 @(':LOGIC') creator of @('st'), respectively.</li>

 <li>For all i &lt; k, there is a stobj export @('fi') returning @('st') with
 @(':EXEC') function @('fi_E') and @(':LOGIC') function @('fi_L') and
 well-guarded parameter lists @('p_E') and @('p_L') for @('fi'), such that the
 following conditions hold.  The lists @('p_E') and @('p_L') agree except in
 one position,which is where @('st') is returned.  The actual parameter at that
 positioni s@('c_i') for @('p_E') and @('a_i') for @('p_L').  Then @('c_j') and
 @('a_j') are returned by the respective calls of @('fi_E') on @('p_E') and
 @('fi_L') on @('p_L').</li>

 </ul>

 <p>For theoretical details pertaining to this topic, see the long comment,
 &ldquo;Essay on the Correctness of Abstract Stobjs&rdquo;, in the ACL2 source
 code.</p>")
other
(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'), @(':stobjs'), 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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(defxdoc stobj-table
  :parents (stobj nested-stobjs)
  :short "A @(see stobj) field mapping stobj names to stobjs"
  :long "<p>See @(see stobj) for basic background on stobjs, and see @(see
 defstobj) for detailed documentation on the syntax and semantics of stobjs,
 including fields specified with @(':type (stobj-table)') or
 @(':type (stobj-table SIZE)').  In the latter case, @('SIZE') must either be a
 natural number or a defined constant whose value is a natural number.  We call
 such fields &mdash; that is, stobj fields specified with
 @(':type (stobj-table)') or @(':type (stobj-table SIZE)') &mdash;
 ``stobj-table fields''; this documentation topic explains them, and it assumes
 familiarity with stobj fields of stobjs as documented in @(see nested-stobjs)
 &mdash; especially, the use of @(tsee stobj-let) to read and write such
 fields.  Note that the documentation for @(see defstobj) shows the default
 names for accessors and updaters; for a stobj-table field, @('TBL'), these are
 @('TBL-GET') and @('TBL-PUT'), respectively.</p>

 <p>For examples of @('stobj-let') usage for stobj-tables, see @(see
 community-book) @('books/system/tests/stobj-table-tests-input.lsp').</p>

 <p>A stobj-table field may be viewed as an association list mapping stobj
 names to corresponding stobjs, so that each stobj name maps to a stobj that
 satisfies the recognizer for that stobj name.  This requirement is not
 enforced in the logic (i.e., in recognizer functions).  But it is essentially
 maintained in raw Lisp as an invariant, except that for efficiency, a
 stobj-table field is implemented as a hash table (again, mapping stobj names
 to corresponding stobjs).  Below we give more details and explain how
 @('stobj-let') may be used to access and update stobjs that are in such a
 table.</p>

 <p>The general forms for stobj-table fields of stobjs are as shown below.</p>

 @({
 (defstobj NAME
   (TBL1 :type (stobj-table))      ; stobj field of default size
   ...
   (TBL2 :type (stobj-table SIZE)) ; stobj field of desired size SIZE
   ...)
 })

 <p>That is, a stobj-table field is a field whose type is of the form
 @('(stobj-table)') or @('(stobj-table SIZE)').  The syntax is thus much like
 the syntax for hash-table fields of stobjs, except that there is no test
 specified for a stobj-table (it is actually @(tsee eq) in raw Lisp).</p>

 <p>As noted above, a stobj-table is conceptually an alist that associates
 stobj names with corresponding stobjs.  We say ``conceptually'' because in
 fact, the recognizer for any stobj-table field is @('t'): there is no
 requirement that it is actually an alist.  It is accessed logically with
 @(tsee hons-assoc-equal), which is a variant of @(tsee assoc) that treats an
 arbitrary object as an alist: only pairs are considered when looking up a key,
 and the final cdr is ignored.  A default value is returned when there is no
 pair with the given key.  A stobj-table field is thus very much like a
 hash-table field.  The key difference (pun somewhat intended) is that each key
 of a stobj-table is the name of a stobj (other than @('state'), i.e., it is a
 user-defined stobj name), and the corresponding value is a stobj satisfying
 the recognizer for that name.</p>

 <p>A common case is that a stobj-table field is the unique field of its parent
 stobj.  In that case we may think of the entire stobj as a stobj-table, and
 that is actually consistent with the implementation: in raw Lisp, if a
 stobj-table field is the sole field of its parent stobj, then that stobj-table
 field is actually the entire stobj; there is not the usual indirection in raw
 Lisp, where a stobj is a vector of fields and the field is accessed as an
 entry in that vector.  (Logically, however, a stobj is always a list of its
 fields, even if there is only one field.)</p>

 <p>Reads and writes of a stobj-table field are much like reads and writes when
 the field is an array of stobjs.  In both cases, one uses @(tsee stobj-let) to
 access and possibly update the desired individual stobj or stobjs.  The syntax
 thus looks as follows, where @('ST') is a stobj name and @('PARENT') is the
 name of a stobj that has a stobj-table accessor with name @('TBL-GET').  Note
 that the first argument of the accessor must be the quotation of the name of
 the bound stobj (thus below, @(''ST') is the quotation of @('ST')) and the
 third argument must be a call of that stobj's creator function.</p>

 @({
 (stobj-let (...                                 ; bindings
             (ST (TBL-GET 'ST PARENT (CREATE-ST)))
             ...
             )
            (...)                                ; producer variables
            (...)                                ; producer
            ...                                  ; consumer
            )
 })

 <p>The @('TBL-GET') call above always returns an object that satisfies the
 recognizer for the stobj, @('ST').  However, that is a fact about evaluation;
 it is not provable in the logic.  Fortunately, @(see guard) verification
 typically adds hypotheses to this effect when necessary.</p>

 <p><b>Remark</b>.  This remark on the implementation may be skipped, but it
 may provide some intuition.  When a stobj name is not bound in the underlying
 hash table, then the default value (in the example above, @('(CREATE-ST)'))
 provides a suitable stobj nonetheless.  And if that stobj name is among the
 producer variables of a @('stobj-let') form, it will be bound in the
 underlying hash table when the @('stobj-let') form completes.  End of
 remark.</p>

 <p>The remainder of this topic explains the use of stobj-tables by following
 the example in @(see community-book) @('std/stobjs/stobj-table.lisp').  The
 first form in that book (after the initial @(tsee in-package) form) is as
 follows.</p>

 @({
 (defstobj stobj-table (tbl :type (stobj-table)))
 })

 <p>This specifies a stobj named @('stobj-table') with a unique field,
 @('tbl').  As noted above, this stobj is the same as its field in raw Lisp, so
 even though it is the field that is truly a stobj-table, it is not
 conceptually problematic to call the entire stobj ``stobj-table''.  This may
 be the most common case for a stobj-table (i.e., being a unique field of a
 stobj).</p>

 <p>The remaining forms in the book are @(see local) to the book, intended to
 illustrate with simple examples how stobj-tables may be used.  The first one
 just introduces a rather trivial stobj.</p>

 @({
 (defstobj st1 fld1)
 })

 <p>The next form puts this stobj into the stobj-table after updating its field
 with a specified value.</p>

 @({
 (defun update-st1-in-tbl (val stobj-table)
   (declare (xargs :stobjs stobj-table))
   (stobj-let ((st1 (tbl-get 'st1 stobj-table (create-st1)))) ; bindings
              (st1)                                        ; producer variable
              (update-fld1 val st1)                        ; producer
              stobj-table                                  ; consumer
              ))
 })

 <p>The form after that accesses the value of @(''st1') in the stobj-table and
 returns its field's value.</p>

 @({
 (defun read-st1-in-tbl1 (stobj-table)
   (declare (xargs :stobjs stobj-table))
   (stobj-let ((st1 (tbl-get 'st1 stobj-table (create-st1)))) ; bindings
              (val)                                        ; producer variable
              (fld1 st1)                                   ; producer
              val                                          ; consumer
              ))
 })

 <p>Next is a check that when a specific value is written for the key @(''st1')
 with the update function defined above, the value subsequently read for key
 @(''st1') is that written value.  The reason for the @('mv') call is that the
 updater returns an updated stobj-table, which therefore must be returned.
 However, @(tsee assert-event) is sufficiently clever to check that the
 first (i.e., ordinary) value returned is non-@('nil').</p>

 @({
 (assert-event
  (let ((stobj-table (update-st1-in-tbl 3 stobj-table)))
    (mv (equal (read-st1-in-tbl1 stobj-table)
               3)
        stobj-table))
  :stobjs-out '(nil stobj-table))
 })

 <p>The computation above is a special case of a standard ``read-over-write''
 property, that after a write, we read the value that was just written.  This
 is proved automatically.</p>

 @({
 (defthm read-over-write-st1-in-tbl
   (implies (stobj-tablep stobj-table)
            (let ((stobj-table (update-st1-in-tbl val stobj-table)))
              (equal (read-st1-in-tbl1 stobj-table)
                     val))))
 })

 <p>The other standard ``read-over-write'' property is that the write for a
 given key doesn't affect the value read for a different key.  The following
 events, admitted automatically, illustrate that property: here, writing a
 value for the key @(''st1') doesn't affect the value read for the key
 @(''st2').</p>

 @({
 (defstobj st2 fld2)

 (defun read-st2-in-tbl (stobj-table)
   (declare (xargs :stobjs stobj-table))
   (stobj-let ((st2 (tbl-get 'st2 stobj-table (create-st2)))) ; bindings
              (val)                                        ; producer variable
              (fld2 st2)                                   ; producer
              val                                          ; consumer
              ))

 (defthm read-over-write-st2-in-tbl
   (implies (stobj-tablep stobj-table)
            (let ((stobj-table-2 (update-st1-in-tbl val stobj-table)))
              (equal (read-st2-in-tbl stobj-table-2)
                     (read-st2-in-tbl stobj-table)))))
 })

 <p>Note that all keys in a stobj-table are names of stobjs.  Consider what
 happens when we evaluate the events in the book above, including the local
 events, and then undo the @(tsee defstobj) event admitting @('st1').  It is
 clear that undoing has removed the symbol @('st1') as a key in the
 stobj-table.</p>

 @({
 ACL2 !>(ld "std/stobjs/stobj-table.lisp" :dir :system)
 [[.. output omitted ..]]
 ACL2 !>(tbl-count stobj-table)
 1
 ACL2 !>:ubt st1
    d       1:x(DEFSTOBJ STOBJ-TABLE (TBL :TYPE #))
 ACL2 !>(tbl-count stobj-table)
 0
 ACL2 !>
 })

 <p>Finally, we remark that there is nothing special about stobj-table fields
 with respect to stobj fields of abstract stobjs.</p>")
other
(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>")
other
(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::nat-to-dec-string), 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)")
other
(defxdoc string-alistp
  :parents (alists acl2-built-ins)
  :short "Recognizer for association lists with strings as keys"
  :long "<p>@('(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.</p>

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

 @(def String-alistp)")
other
(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.  For a related macro that can take an arbitrary number of string
 arguments, 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)")
other
(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') states that its argument is a
 string.</p>

 <p>@('String-downcase') is a Common Lisp function.  See any Common Lisp
 documentation for more information.  Note that the value returned may depend
 on the host Lisp; see @(see soundness), specifically Example 1 in the Section,
 &ldquo;Examples of divergence among Lisp implementations&rdquo;.</p>

 @(def string-downcase)")
other
(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.</p>

 <p>@('String-equal') is a Common Lisp function.  See any Common Lisp
 documentation for more information.  Note that the value returned may depend
 on the host Lisp; see @(see soundness), specifically Example 1 in the Section,
 &ldquo;Examples of divergence among Lisp implementations&rdquo;.</p>

 @(def string-equal)")
other
(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)")
other
(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') states that its argument is a
 string.</p>

 <p>@('String-upcase') is a Common Lisp function.  See any Common Lisp
 documentation for more information.  Note that the value returned may depend
 on the host Lisp; see @(see soundness), specifically Example 1 in the Section,
 &ldquo;Examples of divergence among Lisp implementations&rdquo;.</p>

 @(def string-upcase)")
other
(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<)")
other
(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<=)")
other
(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>)")
other
(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>=)")
other
(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>")
other
(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>")
other
(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)")
other
(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)")
other
(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>")
other
(defxdoc subgoal-loop-limits
  :parents (miscellaneous)
  :short "maximum length of the subgoal stack"
  :long "@({
 General Form:
 (subgoal-loop-limits (w state))
 })

 <p>See @(tsee set-subgoal-loop-limits) for a discussion of how you can set
 this parameter, which can be used to detect simple looping by the prover and
 to cut off some forms of infinite looping.</p>")
other
(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)")
other
(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)")
other
(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>")
other
(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)")
other
(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)")
other
(defxdoc subversive-inductions
  :parents (miscellaneous)
  :short "Why we restrict @(see encapsulate)d recursive functions"
  :long "<p>See @(see subversive-recursions).</p>")
other
(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>")
other
(defxdoc summary
  :parents (output-controls)
  :short "The summary printed at the conclusion of an event"
  :long "<p>At the conclusion of an @(see event) form, ACL2 prints (by default)
 information summarizing the event.  The entire summary may be avoided &mdash;
 see @(see set-inhibit-output-lst) &mdash; or if you prefer, you may inhibit
 just specified components of the summary &mdash; see @(see
 set-inhibited-summary-types).  The components are listed in the constant
 @('*summary-types*') and most are available programmatically: see @(see
 get-event-data).  Some are omitted, however, if they would otherwise be empty.
 Here is a brief summary of the components, listed alphabetically.  Most are
 printed with an initial field indicator, e.g., ``@('Rules: ')''; a few, as
 indicated below, are not.</p>

 <ul>

 <li>@('Errors') (no field indicator): The final error message</li>

 <li>@('Form') (no field indicator): The ``context'' for the event (@(see
 ctx))</li>

 <li>@('Header') (no field indicator): The initial word ``Summary''</li>

 <li>@('Hint-events'): Certain hints (e.g., @(':use') hints) supplied</li>

 <li>@('Redundant'): There is field indicator, but a message is printed that
 notes a redundant event (see @(see redundant-events)) above the rest of the
 summary.  That message is printed even when @('SUMMARY') output or the
 @('REDUNDANT') summary-type is inhibited, if @('EVENT') output is not
 inhibited.</li>

 <li>@('Rules'): @(see Rune)s contributing to the proof or storage of the
 event</li>

 <li>@('Splitter-rules'): Potential causes of case splits (see @(see
 splitter))</li>

 <li>@('Steps') (field indicator is @('"Prover steps counted"')): Prover
 steps (see @(see set-prover-step-limit))</li>

 <li>@('System-attachments'): List of doublets @('(f g)') for which @('f') is a
 system function with attachment @('g') (see @(see defattach)), when @('g')
 differs from the initial attachment to @('f')</li>

 <li>@('Time'): Runtime (or real time; see @(see get-internal-time))</li>

 <li>@('Value'): When an event form under @(tsee progn) or @(tsee encapsulate)
 evaluates to @('(mv nil val state)'), @('val') is printed immediately under
 the summary fields.  (No field indicator)</li>

 <li>@('Warnings'): All warning string summaries printed during processing of
 the event</li>

 </ul>")
other
(defxdoc summary-of-acl2-system-distribution
  :parents (installation-support)
  :short "Summary of ACL2 system distribution"
  :long "<p>This topic discusses a distribution that includes only the ACL2
 system, without the @(see community-books).</p>

 <p>See @(see installation-instructions) for how to obtain a gzipped tarfile that
 contains both the ACL2 sources and community books.  Below we describe the
 ACL2 distribution only (without the community books).  Its files are available
 by obtaining a gzipped tarfile, @(`(:raw (acl2-url-ref "distrib/acl2.tar.gz"
 "acl2.tar.gz"))`).  If you download this file and extract it with</p>

 @({
 tar xfz acl2.tar.gz
 })

 <p>then you will create a subdirectory, @('acl2-sources'), which is
 approximately the usual ACL2 distribution (see @(see installation-instructions))
 without the @('books') subdirectory.  Among its contents, in addition to the
 ACL2 source files, are the following.</p>

 @({
 LICENSE       ; ACL2 license file
 GNUmakefile   ; For use with GNU make
 TAGS          ; Handy for looking at source files with emacs
 TAGS-acl2-doc ; Handy for finding code in books, e.g., with the acl2-doc browser
 acl2-customization-files/ ; Useful for certifying books, e.g., with ACL2(p)
 bin/          ; Contains an executable script, bin/acl2, which invokes ACL2
 doc/          ; ACL2 documentation
 emacs/        ; Some helpful emacs utilities
 })

 <p>Also available are @(`(:raw (acl2-url-ref "distrib/images/"
 "images/"))`), which may contain executables; see @(`(:raw (acl2-url-ref
 "distrib/images/Readme.html" "images/Readme.html"))`)</p>

 <h3>GitHub Distributions</h3>

 <p>We strongly recommend that ACL2 users update their local copies of the
 system and @(see community-books) every time there is an ACL2 release.  While
 that should suffice for many ACL2 users, nevertheless for those who prefer to
 obtain the latest developments, the ACL2 source code and community books are
 available between ACL2 releases, by way of revision control using git.  See
 the <a href='https://github.com/acl2/acl2'>GitHub ACL2 project website</a> for
 more information.</p>")
other
(defxdoc swap-stobjs
  :parents (stobj acl2-built-ins)
  :short "Swap two congruent @(see stobj)s"
  :long "<p>See @(see stobj) for relevant background on single-threaded
 objects.</p>

 <p>The macro call @('(swap-stobjs st1 st2)') is allowed when @('st1') and
 @('st2') are congruent @(see stobj)s.  The logical meaning is simply to return
 the two stobjs in reverse order, @('(list st2 st1)'):</p>

 @(def swap-stobjs)

 <p>However, for purposes of tracking single-threadedness, the result @('(mv
 st2 st1)') of @('(swap-stobjs st1 st2)') is treated as a list of new values
 for the stobjs @('st1') and @('st2'), respectively.  That is, after this call
 of @('swap-stobjs'), the new value of stobj @('st1') is considered to be the
 old value of @('st2'), and the new value of stobj @('st2') is considered to be
 the old value of @('st1').  This is illustrated by the following example.</p>

 @({
 (defstobj st1 fld1)
 (defstobj st2 fld2 :congruent-to st1)
 (defstobj st3 fld3 :congruent-to st1)
 (defun foo (st1 st2)
   (declare (xargs :stobjs (st1 st2)))
   (swap-stobjs st1 st2))
 ; Initialize:
 (update-fld1 3 st1)
 (update-fld2 4 st2)
 ; Swap:
 (foo st1 st2)
 ; Check that the swap took place:
 (assert-event (equal (fld2 st2) 3))
 (assert-event (equal (fld1 st1) 4))
 })

 <p>The example above is essentially the first of several that may be found in
 the @(see community-book), @('books/system/tests/swap-stobjs.lisp').  Those
 examples illustrate that @('swap-stobjs') has the expected effect even when
 stobjs are involved that are bound by @(tsee with-local-stobj) or @(tsee
 stobj-let).  It also explains subtle interaction with @(tsee trans-eval).  For
 another example, see @('books/demos/swap-stobj-fields.lisp').</p>

 <p>In the example above, we call @('foo') rather than calling @('swap-stobjs')
 directly.  That is because @('swap-stobjs') calls must not be made directly in
 the top-level loop.  Instead, put those calls in function bodies or in
 theorems.</p>

 <p>Both inputs to @('swap-stobjs') are required to be @(see stobj)s.  However,
 the usual tracking of stobjs is relaxed during proofs.  See @(see
 live-stobj-in-proof) for an error caused by @(tsee swap-stobjs) during a proof
 when exactly one of the arguments is truly a stobj (i.e., a so-called
 &ldquo;live&rdquo; stobj).</p>")
other
(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)")
other
(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)")
other
(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)
 })")
other
(defxdoc symbol-name-lst
  :parents (symbols acl2-built-ins)
  :short "Lift @(tsee symbol-name) to lists"
  :long "<p>This function returns the list of @(tsee symbol-name)s of a given
 list of symbols.</p>

 @(def symbol-name-lst)")
other
(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>")
other
(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<)")
other
(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>")
other
(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>

 <p>When symbols are read by Common Lisp or ACL2, 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 to 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
 &ldquo;backslash&rdquo; 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>")
other
(defxdoc sync-ephemeral-whs-with-persistent-whs
  :parents (wormhole)
  :short "establishing wormhole coherence"
  :long "@({
  General Form:
  (sync-ephemeral-whs-with-persistent-whs name state)
  })

  <p>where @('name') is the quoted name of a @(tsee wormhole) other than one of
  the built-in ACL2 system wormholes.  It is forbidden to invoke
  @('sync-ephemeral-whs-with-persistent-whs') on the names listed in the
  constant @('*protected-system-wormhole-names*') which includes @('brr') (the
  @(see break-rewrite) wormhole name), @('accumulated-persistence'), and
  @('fc-wormhole') (the name of the wormhole managing @(see
  forward-chaining-reports)), among others.</p>

  <p>If executed on the live state and while in the named wormhole, this
  function moves the wormhole's status from the persistent-whs (located in that
  part of the memory outside of ACL2's state) to the ephemeral-whs (the value
  of the state global variable @('wormhole-status')).  Subsequently,
  @('name')'s persistent-whs is equal to its ephemeral-whs: the @('name')
  wormhole is coherent.  If executed on a state other than the live one or
  while outside of the named wormhole, this function is a no-op.  Of course,
  the next time the @('name') wormhole is entered it will be in a coherent
  state since entry to a wormhole initializes the @('wormhole-status') to the
  persistent-whs.  @('sync-ephemeral-whs-with-persistent-whs') returns the new
  state.</p>

  <p>Logically speaking, this function uses @(tsee read-acl2-oracle) to obtain
  the wormhole's hidden status.  So the output state is almost certainly
  different than the input state.</p>

  <p>See @(see wormhole-programming-tips) for some tips for using this
  function.</p>")
other
(defxdoc syntactically-clean-lambda-objects-theory
  :parents (theories theory-functions rewrite)
  :short "how to specify syntactic cleaning of lambda objects"
  :long "<p>The enabled status of two @('rewrite-lambda-modep') runes are used
  as flags to determine the action taken when eligible @('lambda') objects are
  encountered by the ACL2 rewriter.  See @(see rewrite-lambda-object) and
  @(tsee rewrite-lambda-object-actions).  To prevent the rewriter from diving
  recursively into the body of an eligible @('lambda') object but use a simpler
  syntactic cleaning process instead, the rune @('(:executable-counterpart
  rewrite-lambda-modep)') must be enabled and the rune @('(:definition
  rewrite-lambda-modep)') must be disabled in the then-current theory.  The
  0-ary function @('syntactically-clean-lambda-objects-theory') returns such a
  theory.</p>

  <p>In fact, diving into eligible quoted @('lambda') object constants to
  rewrite the body is the default action when ACL2 starts up.  See @(see
  rewriting-versus-cleaning-up-lambda-objects) for why you might want to change
  the default action when eligible @('lambda') objects are encountered by the
  rewriter.</p>

  <p>The expression @('(syntactically-clean-lambda-objects-theory)')
  macroexpands to the theory expression</p>

  @({
  (e/d ((:executable-counterpart rewrite-lambda-modep))
       ((:definition rewrite-lambda-modep)))
  })

  <p>which is a theory equal to then current theory except that the
  executable-counterpart rune of @('rewrite-lambda-modep') but the definition
  rune is disabled.  This expansion is suitable for use in an @(tsee in-theory)
  event or @(':in-theory') hint (see @(':')@(tsee hints)).</p>

  <p>Both these two runes are initially enabled, so eligible @('lambda') object
  bodies are rewritten by default until and unless some event (e.g., an @(tsee
  in-theory) or @(tsee include-book)) or a superior local subgoal hint changes
  the status of those runes.</p>

  <p>For example, if @('lambda') object rewriting is active you wish to just
  syntactically clean the @('lambda') objects in @('Subgoal 3') of some proof,
  you could use the @(':')@(tsee hints)</p>

  @({
  ("Subgoal 3"
   :in-theory (syntactically-clean-lambda-objects-theory))
  })

  <p>Note that if you also wish to enable or disable other runes in the same
  subgoal you must construct an appropriate theory.</p>

  <p>For example, if in @('Subgoal 3') of some proof you wanted to enable
  @('LEMMA1') and disable @('LEMMA2') in a theory that will also specify
  syntactic cleaning of @('lambda') objects, you might write</p>

  @({
  ("Subgoal 3"
   :in-theory (set-difference-theories
                 (union-theories (syntactically-clean-lambda-objects-theory)
                                 '(LEMMA1))
                 '(LEMMA2)))
  })

  <p>Some users might prefer</p>

  @({
  ("Subgoal 3"
   :in-theory (e/d ((:executable-counterpart rewrite-lambda-modep)
                    LEMMA1)
                   ((:definition rewrite-lambda-modep)
                    LEMMA2)))
  })

  <p>See @(see theories) for general information about theories and how to
  create and use them.</p>")
other
(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>")
other
(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 rewrite-quoted-constant), @(':')@(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'), 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>")
other
(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>")
other
(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.</p>

 <p>The use of @(tsee prog2$) in the second example form above is optional, but
 illustrates how to get the return status.  See @(see sys-call-status).
 @('Sys-call') itself always returns @('nil').</p>

 <p><b>WARNING</b>: The details of how @('sys-call') works can vary among
 different host Lisp implementations!  Consider for example wildcard expansion,
 such as when executing the form @('(sys-call "ls" '("*.lisp"))').  For
 ACL2 built on Allegro CL, CCL, CMUCL, GCL, or SBCL, we have seen this result
 in an error message such as @('"No such file or directory"'), even though
 files with names of the form @('*.lisp') are present in the current
 directory; but for ACL2 built on LispWorks, a list of such filenames is
 printed.</p>

 <p>More generally, we note that @('sys-call') does not provide some features
 that one may expect of a shell.  We mentioned wildcard expansion above; other
 sorts of shell expansion may also not be supported, such as @('~/').
 @('Sys-call') 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
 })

 <p>Another approach is suggested by <a
 href='https://ccl.clozure.com/manual/chapter9.2.html'>a passage in the CCL
 manual</a>: call the shell program.  For example, here is how one might list
 the @('.lisp') files in a directory.</p>

 @({
 (sys-call "sh" '("-c" "ls *.lisp"))
 })

 <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*') can 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).  As noted
 above, host lisps differ on their handling of @('sys-call'); see the raw Lisp
 definition of ACL2 source function @('system-call') for details, including
 exactly the underlying Lisp code that 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.  Also, note that this log is from many
 years ago; the feature shown, @(':AKCL-SET-MV'), is no longer present.)</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>
 })")
other
(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 @('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') after printing as a side effect
 like @(tsee sys-call).  (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>")
other
(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') can be @('nil'), indicating that after the command executes the
 process status returned is 0, indicating a normal exit.  Otherwise @('erp') is
 a non-zero integer, which is the status returned by the process when it
 completes.</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>")
other
(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 @(tsee 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 an integer, which is the status returned by the process
 when it completes.</p>")
other
(defxdoc sysfile
  :parents (books project-dir-alist)
  :short "File representation using ACL2 project directories"
  :long "<p>ACL2 supports relocation of book directories so that those
 books are still treated as certified.  See @(see project-dir-alist).</p>

 <p>A key data structure to support this feature is the <i>sysfile</i>, which
 is a pair of the form @('(:kwd . "relpath")').  Here, @(':kwd') is a key of
 the @('project-dir-alist'), bound to some absolute pathname @('"D/"') of a
 directory, and @('"relpath"') is a string that denotes a pathname relative
 to directory @('"D/"').  Thus, the sysfile @('(:kwd . "relpath")')
 represents the same pathname as @('"D/relpath"').</p>

 <p>(Remark.  The name ``sysfile'' was originally coined to suggest ``system
 file'', suggesting the use of keyword @(':SYSTEM') to indicate a file residing
 in the @(see community-books).  It now extends to @('(:kwd . "relpath")')
 even for @(':kwd') values other than @(':SYSTEM').  But ``sysfile'' is a
 convenient name, and it still seems reasonable since ``system file'' can
 suggest a file of the filesystem.)</p>

 <p>ACL2 rarely generates output that includes sysfiles; they are mostly used
 in the implementation, for example to denote included books in @(see
 certificate) files.  But they are occasionally relevant at the user level; for
 example see @(see add-include-book-dir).</p>

 <p>Finally we discuss the use of sysfiles in @(see certificate) files.  When
 the @(see community-books) directory is a prefix of a @(see full-book-name)
 string, ACL2 may choose to represent that full-book-name as @('(:system
 . "relpath")'), where @('"relpath"') is the result of removing the
 community-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"

  ; sysfile representation
  ; (where "/Users/smith/acl2/acl2/books/" is the community-books directory):
  (:SYSTEM . "std/portcullis.lisp")
 })

 <p>This behavior applies to more than the community-books: it applies to the
 entire @(tsee project-dir-alist).  If that alist associates keyword @(':K')
 with absolute directory name @('"<dir>"'), then a full-book-name with prefix
 @('"<dir>"'), say, @('"<dir>/relpath"'), is written to a @(see
 certificate) file as @('(:K . "relpath")').  This capability supports
 relocating book directories; see @(see project-dir-alist) for a more complete
 discussion.</p>")
*system-attachments-long-prefix*constant
(defconst *system-attachments-long-prefix*
  "<p>This topic concerns advanced methods for modifying the behavior
 of ACL2.  See @(see defattach) for some relevant background.</p>

 <p>If you evaluate the form @('(global-val 'attachments-at-ground-zero (w
 state))'), you will see a list of pairs of the form @('(f . g)'), where @('f')
 is a built-in constrained utility and @('g') is its attachment.  At the end of
 this topic is a list that associates each such @('f') with brief
 documentation (often, just a link).  Users are permitted to modify these
 attachments using @(tsee defattach-system), even without a trust tag (see
 @(see defttag)), because they do not affect soundness.</p>

 <p>Here are two functions that are useful for attaching to many attachable
 0-ary system functions.</p>

 @(def constant-t-function-arity-0)

 @(def constant-nil-function-arity-0)

 <p>To see how to use one of these functions, consider the following example of
 a pair @('(f . g)') as described above, i.e., a system function @('f') that
 comes with attachment @('g').</p>

 @({
 (ASSUME-TRUE-FALSE-AGGRESSIVE-P . CONSTANT-NIL-FUNCTION-ARITY-0)
 })

 <p>Here is how we can make the so-called ``assume-true-false'' algorithm more
 aggressive; see @(see assume-true-false-aggressive-p).</p>

 @({
 (defattach-system assume-true-false-aggressive-p constant-t-function-arity-0)
 })

 <p>The following brief explanations are intentionally brief.  We expect that
 those who want to use such system attachments are comfortable as &ldquo;system
 programmers&rdquo;, so that the brief documentation below is sufficient for
 getting started.  Perusal of the ACL2 source code and its comments can fill in
 details as needed.</p>

 <p>Also see @(see efficiency) for further discussion on making system
 attachments that modify ACL2's default behavior.</p>
")
*attachments-at-ground-zero-doc-alist*constant
(defconst *attachments-at-ground-zero-doc-alist*
  '((acl2x-expansion-alist identity-with-state) (always-do-proofs-during-make-event-expansion constant-nil-function-arity-0
      make-event)
    (ancestors-check ancestors-check-builtin
      "Backchaining control; see @(see
                      use-trivial-ancestors-check).  Source function
                      @('strip-ancestor-literals') might also be useful.")
    (apply$-userfn doppelganger-apply$-userfn)
    (assume-true-false-aggressive-p constant-nil-function-arity-0
      assume-true-false-aggressive-p)
    (badge-userfn doppelganger-badge-userfn)
    (being-openedp-limited-for-nonrec constant-t-function-arity-0
      "Attach to @('constant-nil-function-arity-0') to extend to non-recursively
      defined functions the stack-based limitation on opening
      recursively-defined functions.")
    (brkpt1-brr-data-entry brkpt1-brr-data-entry-builtin
      "See @(see with-brr-data).")
    (brkpt2-brr-data-entry brkpt2-brr-data-entry-builtin
      "See @(see with-brr-data).")
    (conjoin-clause-sets-bound conjoin-clause-sets-bound-builtin
      "Attach to a constant function that returns a natural number (default
      @(`(conjoin-clause-sets-bound-builtin)`)) bounding how large a clause-set
      can be to do smart merging into another clause-set; see comments in the
      definition of conjoin-clause-sets in the ACL2 sources for more
      explanation.")
    (heavy-linear-p constant-nil-function-arity-0
      heavy-linear-p)
    (hide-with-comment-p constant-t-function-arity-0 hide)
    (oncep-tp oncep-tp-builtin free-variables-type-prescription)
    (print-clause-id-okp print-clause-id-okp-builtin
      set-print-clause-ids)
    (quick-and-dirty-srs quick-and-dirty-srs-builtin
      quick-and-dirty-subsumption-replacement-step)
    (relieve-hyp-failure-entry-skip-p relieve-hyp-failure-entry-skip-p-builtin)
    (remove-guard-holders-blocked-by-hide-p constant-t-function-arity-0
      guard-holders)
    (remove-guard-holders-lamp constant-t-function-arity-0
      guard-holders)
    (remove-trivial-equivalences-enabled-p constant-t-function-arity-0
      remove-trivial-equivalences-enabled-p)
    (rewrite-if-avoid-swap constant-nil-function-arity-0
      rewrite-if-avoid-swap)
    (rw-cache-debug rw-cache-debug-builtin)
    (rw-cache-debug-action rw-cache-debug-action-builtin)
    (rw-cacheable-failure-reason rw-cacheable-failure-reason-builtin)
    (set-ld-history-entry-user-data set-ld-history-entry-user-data-default
      ld-history)
    (simplifiable-mv-nth-p constant-t-function-arity-0
      theories-and-primitives)
    (too-many-ifs-post-rewrite too-many-ifs-post-rewrite-builtin
      "Heuristic for discarding rewriter result with
                                &ldquo;too many IFs&rdquo;.  Defeat by
                                attaching @('constant-nil-function-arity-2').")
    (too-many-ifs-pre-rewrite too-many-ifs-pre-rewrite-builtin
      "Heuristic for skipping rewrite when unrewritten
                               result has &ldquo;too many IFs&rdquo;.  Defeat
                               by attaching
                               @('constant-nil-function-arity-2').")
    (untranslate-lambda-object-p constant-t-function-arity-0
      lambda$)
    (update-brr-data-1 update-brr-data-1-builtin
      "See @(see with-brr-data).")
    (update-brr-data-2 update-brr-data-2-builtin
      "See @(see with-brr-data).")
    (use-enhanced-recognizer constant-t-function-arity-0
      "Heuristic for treating @('(equal TERM nil)') and
                              @('(equal nil TERM)') as providing a type for
                              @('TERM') during forward-chaining and other
                              operations that assume such a term to be true.")
    (worse-than worse-than-builtin)
    (worse-than-or-equal worse-than-or-equal-builtin)))
other
(assert-event (let ((from-doc (strip-cars *attachments-at-ground-zero-doc-alist*)) (from-wrld (merge-sort-symbol< (strip-cars (global-val 'attachments-at-ground-zero (w state))))))
    (or (equal from-doc from-wrld)
      (cw "ERROR: Failed check on *attachments-at-ground-zero-doc-alist* in ~
            books/system/doc/acl2-doc.lisp.~|~%Missing from ~
            *attachments-at-ground-zero-doc-alist*:~|~x0~|~%To be deleted ~
            from *attachments-at-ground-zero-doc-alist*:~|~x1"
        (set-difference-eq from-wrld from-doc)
        (set-difference-eq from-doc from-wrld)))))
system-attachments-xdoc-detailsfunction
(defun system-attachments-xdoc-details
  (alist)
  (cond ((endp alist) "")
    (t (let* ((tuple (car alist)) (f (car tuple))
          (g (cadr tuple))
          (doc (cond ((null (cddr tuple)) "[Undocumented: low-level system utility]")
              ((symbolp (caddr tuple)) (concatenate 'string
                  "Documentation: See @(see "
                  (symbol-name (caddr tuple))
                  ")."))
              ((stringp (caddr tuple)) (concatenate 'string "Documentation: " (caddr tuple)))
              (t (er hard
                  'system-attachments-xdoc-details
                  "Unexpected shape for tuple ~x0"
                  (car alist))))))
        (concatenate 'string
          "
 <p>@('"
          (symbol-name f)
          "')<br/>Built-in attachment: @('"
          (symbol-name g)
          "')<br/>"
          doc
          "</p>"
          (system-attachments-xdoc-details (cdr alist)))))))
other
(make-event `(defxdoc system-attachments
    :parents (programming defattach)
    :short "System-level algorithms that users can modify with attachments"
    :long ,(CONCATENATE 'STRING *SYSTEM-ATTACHMENTS-LONG-PREFIX*
              " <h3>Summary of attachable system functions</h3>"
              (SYSTEM-ATTACHMENTS-XDOC-DETAILS
               *ATTACHMENTS-AT-GROUND-ZERO-DOC-ALIST*))))
other
(defxdoc system-utilities
  :parents (programming)
  :short "Some built-in programming utilities pertaining to the ACL2 system"
  :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 utilities that are built
 into the ACL2 system.  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><b>WARNING 1</b>.  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><b>WARNING 2</b>.  These utilities are subject to change.  They were
 developed to support the ACL2 system, and as ACL2 evolves, its developers
 claim the right to modify these functions &mdash; even their input-output
 @(see signature)s.  That said, changes to these functions are likely to be
 quite rare.</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>

 @({
 egrep -e '^; Essay on' *.lisp
 })

 <p>in your ACL2 sources directory, you will see the names of more than 90 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> built-in system
 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.  You may also
 wish to see @(see system-attachments) for how to make a few changes to the
 behavior of ACL2.</p>

 <p>Here is another option for finding a built-in 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 built-in system utilities</h3>

 <p>Every function mentioned below belongs in the constant @(tsee
 *acl2-system-exports*).  Also see @(see acl2-built-ins) for built-in utilities
 that are less relevant to the ACL2 system, and see @(see programming) for
 utilities in general.</p>

 <ul>

 <li>@('(acl2-unwind-protect expl body cleanup1 cleanup2)'): This particularly
 sophisticated utility (warning: for advanced system hackers) is logically just
 the following (where the formals shown above are capitalized).

 @({
 (mv-let (erp val state)
         BODY
         (cond (erp (pprogn CLEANUP1 (mv erp val state)))
               (t   (pprogn CLEANUP2 (mv erp val state)))))
 })

 However, aborts are typically handled by causing the ``cleanup'' forms to be
 executed, in the spirit of Common Lisp's @('unwind-protect').  In typical use
 the cleanup forms restore the values of @(see state) global variables that
 were ``temporarily'' set by @('body').  Note that @('expl') is essentially
 ignored.  For more information see the Essay on Unwind-Protect in the ACL2
 source code.</li>

 <li>@('(add-suffix sym str)'): Extend a symbol @('sym') with a suffix
 expressed as a string @('str').  The resulting symbol is in the same package
 as the original symbol.  For instance, @('(add-suffix 'abc "DEF")') results
 in the symbol @(''abcdef'), in the same package as @(''abc').  See @(tsee
 add-suffix-to-fn) for a variant that may be more appropriate for generating
 new function names.</li>

 <li>@('(add-suffix-to-fn sym suffix)'): Variant of @(tsee add-suffix) that
 puts the new symbol in the @('"ACL2"') package when @('sym') is in the
 @('"COMMON-LISP"') package.  New function symbols cannot be in the
 @('"COMMON-LISP"') package; thus, this utility may be appropriate when
 generating new function names from old ones.</li>

 <li>@('(all-attachments wrld)'): Return a list of all attachment pairs @('(f
 . g)') where @('g') is attached to @('f') (see @(see defattach)) in the @(see
 world), @('wrld'), except for two cases that are ignored for this purpose:
 [warrant]s, and attachments introduced with a non-@('nil') value of
 @(':skip-checks').  To obtain the attachment to a function symbol @('f'),
 without the restrictions above and with value @('nil') if there is no
 attachment to @('f'), evaluate @('(cdr (attachment-pair 'f wrld))').  To
 obtain the list of all built-in attachments, evaluate @('(global-val
 'attachments-at-ground-zero (w state))').</li>

 <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.  This may become deprecated, and is just a macro expanding to
 a corresponding call of @('all-fnnames1'); see @('all-fnnames'),
 @('all-fnnames-lst'), and @('all-fnnames1'), below.</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.  This may become deprecated, and is just a macro
 expanding to a corresponding call of @('all-fnnames1'); see @('all-fnnames'),
 @('all-fnnames-lst'), and @('all-fnnames1'), below.</li>

 <li>@('(all-fnnames term)'): Return a list of all function symbols called in
 the given term.  This is a macro call expanding to @('(all-fnnames1 nil term
 nil)').</li>

 <li>@('(all-fnnames-lst lst)'): Return a list of all function symbols called
 in the given list of terms.  This is a macro call expanding to
 @('(all-fnnames1 t lst nil)').</li>

 <li>@('(all-fnnames1 flg x acc)'): Accumulate into @('acc') the function
 symbols called in the given term or list of terms, @('x'), according to
 whether @('flg') is @('nil') (for a term) or not @('nil') (for a list of
 terms), respectively.</li>

 <li>@('(all-vars x)'): For a @(tsee pseudo-termp) @('x'), return a
 duplicate-free list of all 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 (translated but unnormalized) 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-term fn args)'): Returns a @(see term) with function symbol (or
 @(see lambda) expression) @('fn') and arguments @('args').  Evaluation may be
 performed for calls of primitives &mdash; that is, built-in functions without
 definitions &mdash; on arguments that are quoted constants, for example as
 follows.

 @({
 ACL2 !>(cons-term 'coerce (list ''"abc" ''list))
 '(#\a #\b #\c)
 ACL2 !>
 })

 To avoid such evaluation, 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>@('(doublet-listp x)'): Returns @('t') if @('lst') is a list of
 two-element lists @('(x1 x2)'), else @('nil').</li>

 <li>@('(dumb-negate-lit t1)'): For the given @(see term) @('t1'), return a
 term that is propositionally equivalent to @('(not t1)').</li>

 <li>@('(dumb-occur x y)'): Return @('t') if the term @('x') occurs free in the
 term @('y'), but without looking for @('x') inside of quoted constants; else,
 returns @('nil').</li>

 <li>@('(dumb-occur-var x y)'): Return @('t') if the variable @('x') occurs
 free in the term @('y'), else @('nil').  This is the same as @('dumb-occur'),
 but optimized for the case that @('x') is a variable.</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>@('(fix-pkg pkg)'): Returns @('pkg'), which should be @('nil') or a
 non-empty string, with one exception: if @('pkg') is
 @(`*main-lisp-package-name*`) then @('"ACL2"') is returned.</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)'): For a @(tsee pseudo-termp) @('(fn arg1 ... argk)'),
 true when @('fn') is a @(tsee lambda) expression</li>

 <li>@('(flatten-ands-in-lit term)'): Returns a list of terms whose conjunction
 is equivalent to the given term (which satisfies @(tsee pseudo-termp)),
 obtained by flattening its conjunctive structure.  For example,
 @('(flatten-ands-in-lit '(if (if x y 'nil) z 'nil))') is the list @('(x y
 z)').</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-defun-event name w)'): For the given name of a defined function in
 the current ACL2 @(see world) @('w'), return its @(tsee defun) form.  Note
 that this applies to both @(':')@(tsee logic)-mode and @(':')@(tsee
 program)-mode functions, in spite of the name, ``logical'' (which is actually
 intended to distinguish from ``raw Lisp'').</li>

 <li>@('(get-event name w)'): For the given name of an event in the current
 ACL2 @(see world) @('w'), return that event.  Typically there is only one such
 event, but for built-in functions the most recent event might be a variant of
 a @(tsee verify-termination) event, so consider using @('get-defun-event') for
 names of functions (see above).</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>@('(io? token commentp shape vars body &key ...)'): This is a complex
 macro that may be most fully understood by reading the source code, including
 comments in its definition and examples of its use.  But the following
 example from the definition of source function @('print-failure1') may get the
 idea across.

 @({
     (io? summary nil state (channel)
          (fms *proof-failure-string* nil channel state nil))
 })

 This is essentially just the @('body') argument, which here is the indicated
 @(tsee fms) call, but where, going through the other arguments:

   <ul>

   <li>@('summary') &mdash; evaluation only takes place when @('summary')
   output is enabled (see @(see set-inhibit-output-lst));</li>

   <li>@('nil') &mdash; don't enter a wormhole;</li>

   <li>@('state') &mdash; the body (which here is the @('fms') call) returns a
   single @('state') value; and finally</li>

   <li>@('channel') &mdash; this is the list of free variables in the
   body (which here is the @('fms') call).</li>

   </ul>
 </li>

 <li>@('(known-package-alist state)'): Returns a list of package entries, as
 explained in the definition of @('make-package-entry') in ACL2 sources, which
 is followed by simple accessor definitions (all in file @('axioms.lisp') as of
 this writing).  This list includes entries for hidden packages (see @(see
 hidden-death-package)).  As a package is introduced, its package entry is
 pushed on the front of the existing known-package-alist.  Note that this list
 can be accessed directly from a @(see world), @('w'), with: @('(global-val
 'known-package-alist w)').</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>@('(legal-constantp name)'): Returns @('t') if @('name') is a legal
 constant name, else @('nil').</li>

 <li>@('(legal-variablep name)'): Returns @('t') if @('name') is a legal
 variable name, else @('nil').  For example, @('x') is a legal variable name
 but the following are not: @(':abc'), @('t'), @('nil'), @('&a') (a lambda
 keyword), @('*c*') (syntax of a constant), and @('pi') (a Common Lisp
 constant).</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 the @('lambda') expression with
 formal parameters @('args') and body @('body').</li>

 <li>@('(make-lambda-application formals body actuals)'): Return the
 @('lambda') application that is essentially @('((lambda formals body)
 . actuals)').  However, extra formals and corresponding actuals are added when
 @('body') has free variables that do not belong to @('formals'), because
 lambdas must be closed in ACL2.  A similar function is @('make-lambda-term'),
 but that one does not drop unused formals, while @('make-lambda-application')
 does drop them.</li>

 <li>@('(make-lambda-term formals actuals body)'): Return the @('lambda')
 application that is essentially @('((lambda formals body) . actuals)').
 However, extra formals and corresponding actuals are added when @('body') has
 free variables that do not belong to @('formals'), because lambdas must be
 closed in ACL2.  A similar function is @('make-lambda-application'), but that
 one drops unused formals, while @('make-lambda-term') does not.</li>

 <li>@('(maybe-convert-to-mv uterm)'): Given the untranslated @(see term)
 @('uterm'), replace each of its top-level calls of @(tsee list) by a call of
 @(tsee mv) on the same arguments.</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>@('(partition-rest-and-keyword-args x keys)'): @('x') should be a list of
 the form @('(a1 ... an :key1 v1 ... :keyk vk)'), where no @('ai') is a
 keyword.  The result is @('(mv erp rest alist)'), where @('erp') is
 non-@('nil') if and only if the keyword section of @('x') (that is, starting
 with @(':key1')) is ill-formed, that is: some @(':keyi') is not a keyword,
 @(':keyi') and @(':keyj') are the same for some distinct i and j, or some
 @(':keyi') is not a member of @('keys').  When @('erp') is @('nil'), then
 @('rest') is @('(a1 ... an)') and alist is equivalent (as a mapping) to
 @('((:key1 . v1) ... (:keyk . vk))').</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 @(see 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 @('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') or @(':df')
 each symbol that is not a @(see stobj) input &mdash; generally @('nil'), but
 @(':df') if the formal parameter is declared to be a df (see @(see df)).  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 the list described below
 whose length @('L') is the number of return values of @('fn') &mdash; that is,
 @('L') is 1 unless @('fn') returns multiple values.  First suppose that @('L')
 is 1; say the stobjs-out list is @('(s)').  If @('fn') returns a stobj then
 @('s') is that stobj; if @('fn') returns a @(see df) then @('s') is @(':df');
 and otherwise @('s') is @('nil').  Otherwise, @('L') is greater than 1.  Then
 for each @('i') less than @('L'), 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 @(':df') if calls of @('fn') are df{i}
 expressions (see @(see df), else @('nil').  Note that @('fn') must be a
 symbol, not a @(see lambda) expression.  Moreover @('fn') must not be a member
 of the list value of the constant @('*stobjs-out-invalid*'), i.e., the list
 @(`*stobjs-out-invalid*`), 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').  @('Alist') should be an alist that associates symbols with @(tsee
 pseudo-termp)s, and @('term') should also satisfy @('pseudo-termp').  Note
 that the substitution process evaluates calls of primitives on quoted
 constants, essentially using @(tsee cons-term).</li>

 <li>@('(subsequencep lst1 lst2)'): Determine whether the list lst1 is a
 subsequence of the list lst2, although not necessarily a proper
 subsequence.</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-expr1 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').  A more complex function (perhaps a bit less likely to stay forever
 unchanged), @('subst-equiv-expr'), may be found in the source code; it can
 substitute one expression for another when the two are equivalent, but not
 necessarily equal.</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') if @('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>@('(symbol-doublet-listp lst)'): Returns @('t') if @('lst') is a list of
 two-element lists @('(x1 x2)') where @('x1') is a symbol, else @('nil').</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'),
 @('translate1-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>@('(translate-hints name-tree lst ctx wrld state)'): Translate a given
 list of user-level hints, @('lst'), to internal form.  NOTE: this function
 returns an @(see error-triple), and it checks the syntax of @('lst').  Its
 documentation essentially resides in a comment in source function
 @('translate-hints1').</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>

 ")
other
(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>")
other
(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>")
other
(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>")
other
(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') with exceptions
 noted below; @('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
 expands 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 @('tests') in the given
 @(tsee world).  Often you can provide a suitable expression for @('world'),
 for example, @('(w state)').</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.  Note that attachments
 are allowed when evaluating a table guard (see @(see defattach)).  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.  See @(see
 set-table-guard) for a convenient way to set a table's @(':guard') to produce
 user-friendly error messages.</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 following two special cases, the
 @('key') and @('value') terms may not contain any variables: when the table is
 named @(tsee acl2-defaults-table); or when the table's @(':guard') is a call
 of the unary function @('strict-table-guard'), which returns its argument
 unchanged but indicates this restriction on variables for specifying keys and
 values.  Essentially, the keys and values used in @(see events) setting such
 tables 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>This event sets the @(':guard') of the named table to @('term'), provided
 the following requirements are met.  The named table must be empty and it must
 not have been assigned a @(':guard') yet.  @('Term') (which is not evaluated)
 should be a term that mentions at most the variables @('KEY'), @('VAL'),
 @('WORLD'), @('ENS'), and @('STATE').  In the common case @('term') will
 evaluate to a single value, but it can return two values as discussed later
 below; either way, it must not return @('STATE').</p>

 <p>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), @('ENS') bound to the enabled structure representing the current
 theory, and @('STATE') bound to the ACL2 @(see state).  The term is evaluated.
 An error will be caused by the @(':put') if the result of the evaluation is
 @('nil') when a single value is returned; what if two values are returned?</p>

 <p>If the term returns multiple values @('(mv okp msg)'), then an error will
 be caused if @('okp') is @('nil').  In that case, if @('msg') is also @('nil')
 then a generic error message is printed about the illegal key/value pair, just
 as in the single-value return case.  Otherwise @('msg') should be a @(tsee
 msgp) &mdash; a string or a cons suitable for printing with the @(tsee fmt)
 directive, @('~@').  In that case, @('msg') is printed (using @(tsee fmt)
 @('~@')) instead of the generic error message.  Here is a simple example
 adapted from former code in the ACL2 sources.</p>

 @({
 (defun my-table-guard (fn val wrld)
   (let ((msg0 ; nil if fn/val is OK as a key/value pair, else a msg
          (my-table-guard-msg fn val wrld)))
     (cond
      (msg0 (mv nil
                (msg
                 "Illegal my-table key and value (see :DOC ~
                  memoize-partial):~|key = ~y0value  = ~y1Reason:~%~@2~|~%"
                 fn val msg0)))
      (t (mv t nil)))))

 (table my-table nil nil
        :guard
        (my-table-guard key val world))
 })

 <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>")
other
(defxdoc tail-biting
  :parents (debugging)
  :short "Rewriting a true term to @('NIL')"
  :long "<p>On rare occasions, a true term can @(see rewrite) to @('NIL').
 Such ``tail-biting'' behavior can make the prover fail to prove a theorem but
 will not make it ``prove'' a non-theorem.  This topic explains this behavior,
 first with one paragraph explaining it in high-level terms and then, for those
 interested in details, with a specific example.  That example includes
 discussion that exposes more of the ACL2 implementation than is usually
 exposed in documentation topics, so we expect that most readers will skip
 it.</p>

 <p>When backchaining to rewrite a hypothesis @('H') of a @(see rewrite) or
 @(see linear) rule, ACL2 uses the following heuristic: assume that @('H') is
 false when trying to prove it.  That is sound: proposition @('P') is
 equivalent to proposition @('(implies (not P) P)').  We do not discuss why
 ACL2 does this or why it rarely results in so-called ``tail-biting'':
 rewriting the hypothesis to @('NIL') by using the fact that it has been
 assumed false.  But that can happen on rare occasions.  So if you see a term
 rewrite to @('NIL') when you know it to be true, consider whether this is
 because it was encountered earlier during the backchaining process, when it
 was assumed false.</p>

 <p>===== Maybe stop here (lower-level explanation follows)! =====</p>

 <p>The example below shows how tail-biting can happen.  As noted above,
 beware: this explanation is closer to the implementation than is found in most
 of the ACL2 documentation.  We give the example in full first, and then we
 conclude with a more concise summary.  Key to this explanation is the notion
 of the <i>ancestors-stack</i>, which is a data structure kept by the rewriter
 as it backchains through hypotheses, to record the negation of each hypothesis
 encountered during backchaining.</p>

 <p>We begin with a very simple definition and theorem.  Note that we treat
 @(tsee member) below as @(tsee member-equal), to simplify the exposition.</p>

 @({
 (defun copylist (x)
   (if (endp x)
       nil
       (cons (car x) (copylist (cdr x)))))

 (defthm key-rule
   (implies
    (not (member a lst)) ; hypothesis later denoted as ``H''
    (not (member a (copylist lst)))))
 })

 <p>The following ``weird'' rule backchains from @('(member a (cdr lst))') to
 @('(member a lst)'), sort of un-opening @('member').</p>

 @({
 (defthm weird
   (implies (and (consp lst)
                 (member a lst)
                 (not (equal a (car lst))))
            (member a (cdr lst))))
 })

 <p>Now here is our main theorem.  It ought to follow by simplification from
 @('key-rule') above, if we can just establish the hypothesis @('H') of
 @('key-rule') from the hypotheses of @('main').  The instance of @('H') is
 @('(not (member aaa (cdr xxx)))').  The rewriter cannot establish this because
 it requires a proof by induction.  So the proof is bound to fail here.</p>

 @({
 (defthm main
   (implies (and (consp (cdr xxx))
                 (nat-listp xxx)
                 (symbolp aaa))
            (not (member aaa (copylist (cdr xxx)))))
   :hints (("Goal"
            :do-not-induct t
            :do-not '(eliminate-destructors))))
 })

 <p>So we decide to monitor key-rule and see why it failed:</p>

 @({
 (monitor! '(:rewrite key-rule) t)

 (defthm main ...) ; exactly as above

 :eval
 :a!
 })

 <p>And we see that @(tsee brr) reports that ``@(':HYP 1 rewrote to 'NIL')'',
 i.e., that the relevant instance of @('H'), @('(not (member aaa (cdr xxx)))'),
 rewrote to @('NIL').  This seems to suggest @('aaa') is in @('(cdr xxx)').</p>

 <p>But we know it can't be!  The hypotheses of main say @('aaa') is a symbol
 and @('xxx') is a list of natural numbers.  So @('aaa') can't be in @('(cdr
 xxx)'). We can prove it:</p>

 @({
 (defthm hyps-of-main-imply-hyp-1
   (implies (and (consp (cdr xxx))
                 (nat-listp xxx)
                 (symbolp aaa))
            (not (member aaa (cdr xxx)))))
 })

 <p>And using that rule we can now prove @('main'):</p>

 @({
 (defthm main
   (implies (and (consp (cdr xxx))
                 (nat-listp xxx)
                 (symbolp aaa))
            (not (member aaa (copylist (cdr xxx)))))
   :hints (("Goal"
            :do-not-induct t
            :do-not '(eliminate-destructors))))
 })

 <p>So the question is: why did the hypothesis of @('key-rule')
 rewrite to @('NIL')?</p>

 <p>Let's undo back through @('hyps-of-main-imply-hyp-1') and monitor
 @('key-rule'), @('weird'), and the definition of @(tsee member-equal), and
 also @(see trace) system function @('ancestors-check-builtin'), which queries
 the ancestor-stack, and then repeat the doomed proof attempt for
 @('main').</p>

 @({
 (ubt! 'hyps-of-main-imply-hyp-1)
 (monitor '(:rewrite key-rule) ''(:go))
 (monitor '(:rewrite weird) ''(:go))
 (monitor '(:definition member-equal) ''(:go))
 (trace$ ancestors-check-builtin)

 (defthm main
   (implies (and (consp (cdr xxx))
                 (nat-listp xxx)
                 (symbolp aaa))
            (not (member aaa (copylist (cdr xxx)))))
   :hints (("Goal"
            :do-not-induct t
            :do-not '(eliminate-destructors))))
 })

 <p>Here is the series of breaks on (:REWRITE WEIRD), except that the second
 break is elided because you will see at the subsequent ``2x (:REWRITE WEIRD)
 failed...''  that everything that goes on there is irrelevant.  Also deleted
 are some irrelevant calls of @('ancestors-check-builtin'), but the important
 one remains.</p>

 @({
 (1 Breaking (:REWRITE KEY-RULE) on (MEMBER-EQUAL AAA (COPYLIST (CDR XXX))):
 1 ACL2 >:GO

 (2 Breaking (:REWRITE WEIRD) on (MEMBER-EQUAL AAA (CDR XXX)):
 ...
 2x (:REWRITE WEIRD) failed because :HYP 2 rewrote to
 (MEMBER-EQUAL AAA (CDR XXX)).
 2)

 (2 Breaking (:DEFINITION MEMBER-EQUAL) on (MEMBER-EQUAL AAA (CDR XXX)):
 2 ACL2 >:GO

 (3 Breaking (:REWRITE WEIRD) on (MEMBER-EQUAL AAA (CDR (CDR XXX))):
 3 ACL2 >:GO
 1> (ANCESTORS-CHECK-BUILTIN (MEMBER-EQUAL AAA (CDR XXX))
                             (((MEMBER-EQUAL AAA (CDR XXX))
                               (MEMBER-EQUAL AAA (CDR XXX))
                               2 2 0 ((:REWRITE KEY-RULE))
                               . 1))
                             ((:REWRITE WEIRD)))
 <1 (ANCESTORS-CHECK-BUILTIN T T)

 3 (:REWRITE WEIRD) produced 'T.
 3)

 2 (:DEFINITION MEMBER-EQUAL) produced 'T.
 2)

 1x (:REWRITE KEY-RULE) failed because :HYP 1 rewrote to 'NIL.  (See
 :DOC tail-biting if this surprises you.)
 1)
 })

 <p>So we've entered the break on @('key-rule') and backchained to prove its
 hypothesis, @('(not (member aaa (cdr xxx)))').  We thus assume the negation,
 @('(member aaa (cdr xxx))'), on the ancestors stack and then open @('(member
 aaa (cdr xxx))') with the definition.  That results in a call of @('(member
 aaa (cdr (cdr xxx)))') and we backchain through @('weird') to @('(member
 aaa (cdr xxx))') and find it assumed true (on the ancestors-stack).  So
 @('weird') rewrites @('(member-aaa (cdr (cdr xxx)))') to
 @('T') (propositionally) and so @('member-equal') returns @('T'), so @('H')
 rewrites to @('NIL').</p>

 <p>This is not unsound; it is just tail biting.  Here is a summary of what has
 happened.</p>

 <p>1. Attempt to rewrite @('(not (member aaa (copylist (cdr xxx))))') to
 @('T').</p>

 <p>2. Attempt to rewrite @('(member aaa (copylist (cdr xxx)))') to
 @('NIL').</p>

 <p>3. Backchain with @('key-rule') to @('(not (member aaa (cdr xxx)))').</p>

 <p>4. Assume @('(member aaa (cdr xxx))') by putting it on the ancestors-stack.
 This is sound because we are trying to prove @('(not (member aaa (cdr
 xxx)))'), and it is sound to assume @('(not P)') when proving @('P').</p>

 <p>5. Expand @('(member aaa (cdr xxx))'), given @('(consp (cdr xxx))'), to
 @('(or (equal aaa (cadr xxx)) (member aaa (cddr xxx)))')</p>

 <p>6. Rewrite @('(member aaa (cddr xxx))')) using @('weird').</p>

 <p>7. Backchain with weird on (member aaa (cddr xxx)) and relieve its
 hypotheses under the substitution @('a := aaa'), @('lst := (cdr xxx)').

 <ul>

 <li>a. @('(consp (cdr xxx))') is true (hypothesis of @('main')).</li>

 <li>b. @('(member aaa (cdr xxx))') is true (TAIL BITING!).</li>

 <li>c. @('(not (equal aaa (car (cdr xxx))))') is true, presumably from
 expansion of hypotheses of @('main').</li>

 </ul></p>

 <p>8. So @('weird') applies, hence the following are true:

 <ul>

 <li>From 6. @('(member aaa (cddr xxx))')</li>

 <li>From 5. @('(member aaa (cdr xxx))')</li>

 </ul>

 So 3 fails because @('(not (member aaa (cdr xxx)))') rewrites to @('NIL').</p>
 ")
other
(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:</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 (though it takes some effort, including lemmas, to
 get ACL2 to prove it).</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 first-n-ac)

 @(def take)")
other
(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 ACL2 @(csee Workshops)
 pages and on the <a
 href='http://www.cs.utexas.edu/users/moore/acl2/seminar/'>University of Texas
 ACL2 Seminar page</a>.</p>
 ")
other
(defxdoc tame
  :parents (apply$)
  :short "Definitions of the various notions of tameness"
  :long "<p>The adjective ``tame'' can be applied to four different kinds of
  objects, @('LAMBDA') objects, function symbols, expressions, and lists of
  expressions.  Formally, these notions are defined mutually recursively as the
  macro @('tamep-lambdap') and the @(':logic') mode functions named
  @('tamep-functionp'), @('tamep'), and @('suitably-tamep-listp'),
  respectively.  We exhibit the formal definitions at the end of this
  documentation.</p>

  <h3>Definitions</h3>

  <ul>

  <li><b>tame @('LAMBDA') object</b> aka @('tamep-lambdap'): An object is a
  tame @('LAMBDA') object if is of the form @('(LAMBDA vars body)') or
  @('(LAMBDA vars dcl body)') where @('vars') is a list of symbols and
  @('body') is a tame expression.  Formally, an object @('x') is a tame
  @('LAMBDA') object iff @('(tamep-lambdap x)').  @('Tamep-lambdap') is
  actually a macro.</li>

  <li><b>tame function</b> aka @('tamep-functionp'): An object is a <i>tame
  function</i> iff it is either (a) a badged symbol and ilks is @('T'), or (b)
  a tame @('LAMBDA') object (see above).  Formally, an object @('x') is a tame
  function iff @('(tamep-functionp x)').</li>

  <li><b>tame expression</b> aka @('tamep'): An object is a <i>tame
  expression</i> iff it is a symbol, a quoted constant, the call of an badged
  function symbol on the correct number of suitably tame expressions with
  respect to the ilks of the function symbol, or the call of a tame @('LAMBDA')
  expression on the correct number of tame expressions.  Formally, an object
  @('x') is a tame expression iff @('(tamep x)').  Note that tameness implies
  every function symbol in the expression is badged but <i>not necessarily
  warranted</i>.</li>

  <li><b>suitably tame with (respect to arity and ilks)</b> aka
  @('suitably-tamep-listp'): A list of objects @('x') is <i>suitably tame</i>
  with respect to an arity @('n') and a list of @('ilks') iff @('x') is a true
  list of length @('n'), and when an ilk is @(':FN') the corresponding object
  is a <i>quoted</i> tame function, when an ilk is @(':EXPR') the object is a
  <i>quoted</i> tame expression, and when an ilk is @('NIL') the object is a
  tame expression.  Formally, an object @('x') is suitably tame with respect to
  @('n') and @('ilks') iff @('(suitably-tamep-listp n ilks x)').   Note in
  particular our use of the word ``quoted'' above.  We illustrate this in the
  example below.</li>

  </ul>

  <p>Note that the various notions of tameness make no mention of whether the
  function symbols involved are in @(':program') or @(':logic') mode.  The
  function symbols must have badges but need not have warrants.</p>

  <p>Intuitively, a tame expression can be built out of functions that are not
  themselves tame, e.g., scions, by making sure that every @(':FN') slot is
  occupied by a quoted tame function.  Put another way, if we were to trace the
  calls of @('apply$') while evaluating a tame expression every branch
  eventually bottoms out on a call of a primitive.  This is illustrated
  below.</p>

  <h3>Examples</h3>

  <p>We assume the following events have been processed.</p>

  @({
  (include-book "projects/apply/top" :dir :system)

  (defun$ sq (x) (* x x))

  (defun$ foldr (lst fn init)
    (if (endp lst)
        init
        (apply$ fn
                (list (car lst)
                      (foldr (cdr lst) fn init)))))
  })

  <p>@('Sq') and @('foldr') above are defined as @(':logic') mode functions and
  are badged and warranted (note the use of @('defun$')).  But for our purposes
  they could have been introduced by @('defun') in @(':program') mode and then
  badged with two calls of @('defbadge').</p>

  <p>As a result, we see the following badges:</p>

  <code>
  symbol           badge

  CONS    (APPLY$-BADGE 2 1 . T)  ; . T means all args ordinary
  SQ      (APPLY$-BADGE 1 1 . T)  ; . T means all args ordinary
  FOLDR   (APPLY$-BADGE 1 1 NIL :FN NIL)
  </code>

  <p>Consider the following expression.</p>

  @({
  (foldr lst (lambda$ (x y) (foldr y 'cons (list (sq x)))) nil)
  })

  <p>Forgetting about tameness for a moment, what does this term compute?
  Study the definition of @('foldr') if you're not familiar with it and work it
  out!  Answer: It collects, in reverse order, the squares of the elements of
  @('lst').  E.g., if @('lst') is @('(1 2 3 4)') the value of the @('foldr')
  expression above is @('(16 9 4 1)').</p>

  <p>But we are interested in whether it is tame.  Tameness is a concept
  applied to objects representing formal (fully translated) terms (or
  components of terms in the case of ``tame functions,'' ``tame lambdas,''
  etc.).  Saying ``<i>x</i> is a tame expression'' is just a colloquial way of
  saying ``@('(tamep ')<i>x</i>@(')') = @('t').  So we can evaluate this
  term in the top-level ACL2 loop,</p>

  @({
  (tamep '(foldr lst (lambda$ (x y) (foldr y 'cons (list (sq x)))) nil))
  })

  <p>and the result is @('nil') because @('lambda$') is not a ``badged function
  symbol.'' In fact, @('lambda$') is not a function symbol.  It is a macro.
  We're really interested in the formal translation of the @('foldr')
  expression.  One way to understand the situation is that @('tamep') does not
  expand macros.</p>

  <p>The translation of the above term is</p>

  @({
  (FOLDR LST
         '(LAMBDA (X Y)
                  (DECLARE (IGNORABLE X Y))
                  (RETURN-LAST 'PROGN
                               '(LAMBDA$ (X Y)
                                         (FOLDR Y 'CONS (LIST (SQ X))))
                               (FOLDR Y 'CONS (CONS (SQ X) 'NIL))))
         'NIL)
  })

  <p>The @('RETURN-LAST') subterm is a marker that records the original
  user-supplied @('lambda$') expression, which is needed during compilation and
  execution in raw Lisp.  But the value of that @('RETURN-LAST') is the
  expected @('FOLDR') expression in its last argument.  To simplify our
  discussion of tameness let's determine whether the following equivalent term
  is tame.</p>

  @({
  (FOLDR LST
         '(LAMBDA (X Y)
            (FOLDR Y
                   'CONS
                   (CONS (SQ X) 'NIL)))
         'NIL)
  })

  <p>The answer is yes, it is a tame expression.  In particular</p>

  @({
  (tamep '(FOLDR LST
                 '(LAMBDA (X Y)
                    (FOLDR Y
                           'CONS
                           (CONS (SQ X) 'NIL)))
                 'NIL))
  = T
  })

  <p>By the way, @('tamep') answers the same way on the quotation of the
  actual translation of the @('foldr') term.</p>

  <p>We explain below how @('tamep') computes this result.  But before we dive
  into details consider what this example illustrates.  @('FOLDR') is <i>not a
  tame function</i> according to the definitions above. But it can be used in
  the construction of tame expressions provided, mainly, that its second
  argument is a quoted tame function.  Indeed, the example illustrates that we
  can even call @('FOLDR') within the @('LAMBDA') expression passed to another
  @('FOLDR') and still have a tame expression.</p>

  <p>If we were to @(tsee trace$) the functions @('tamep'),
  @('tamep-functionp'), and @('suitably-tamep-listp'), and then call @('tamep')
  on the @('FOLDR') term above we would see a tree of calls of the various
  tameness notions.  Here are selected calls from that tree.  All of the calls
  return @('T').  We discuss each of these calls below.</p>

  <code>
  (tamep '(CONS (SQ X) 'NIL))                                    ; [1]

  (suitably-tamep-listp 3                                        ; [2]
                        '(NIL :FN NIL)
                        '(Y 'CONS (CONS (SQ X) 'NIL)))

  (tamep '(FOLDR Y 'CONS (CONS (SQ X) 'NIL)))                    ; [3]

  (tamep-functionp '(LAMBDA (X Y)                                ; [4]
                            (FOLDR Y 'CONS (CONS (SQ X) 'NIL))))

  (tamep '(FOLDR LST                                             ; [5]
                 '(LAMBDA (X Y)
                          (FOLDR Y 'CONS (CONS (SQ X) 'NIL)))
                 'NIL))
  </code>

  <p>@('[1]'): The object here, @('(CONS (SQ X) 'NIL)'), is tame because both
  @('CONS') and @('SQ') are tame functions and they are applied to the correct
  number of tame expressions.</p>

  <p>@('[2]'): The list of objects here, @('(Y 'CONS (CONS (SQ X) 'NIL))') is a
  suitably tame list of length @('3') with ilks @('NIL'), @(':FN'), and
  @('NIL') because @('Y') and @(''NIL') are both tame and @(''CONS') is a
  <i>quoted</i> tame function, @('CONS').</p>

  <p>@('[3]'): The object here is tame because @('FOLDR') is a badged function
  of arity 3 and its actuals are suitably tame with respect to its arity and
  ilks as shown by example @('[2]').</p>

  <p>@('[4]'): The @('LAMBDA') object here is a tame function because it is of
  the form @('(LAMBDA vars body)'), where @('vars') is the list of symbols
  @('(X Y)') and body is the tame object shown in example @('[4]').</p>

  <p>@('[5]'): The object here, a call of @('FOLDR'), is tame because there are
  3 actuals, the first and third are tame expressions and the second is a
  <i>quoted</i> tame function as shown in Example @('[4]').</p>

  <h3>Logical Definitions</h3>

  <p>The various notions of tameness, @('tamep-functionp'), @('tamep'), and
  @('suitably-tamep-listp'), are defined mutually recursively as @(':logic')
  mode functions.  The definition employs the macro @('tamep-lambdap'), which
  is used by @('tamep-functionp') to handle the @('LAMBDA') case.</p>

  @(def tamep-functionp)

  @(def tamep)

  @(def suitably-tamep-listp)

  @(def tamep-lambdap)

  <p>At the top-level of the ACL2 loop you can determine whether an object
  satisfies one of these predicates by calling the appropriate formal notion on
  the object.  But because these functions are defined in terms of @(tsee
  badge) these notions of tameness are evaluable only in the evaluation
  theory (where @(tsee warrant)s are implicitly assumed).  If you want to prove
  that an object is tame, you may need warrant hypotheses.  See @(see
  guarantees-of-the-top-level-loop).</p>")
other
(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 @('(get-tau-runes (w state))').</p>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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 ensure 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 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 topic='@(url type-reasoning)'>type
 reasoning</see> (using @(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 @(see multiple-value)s 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 @(tsee mv-nth).
 Because ACL2's rewriter gives special handling to @('mv-nth') by default,
 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>")
other
(defxdoc tc
  :parents (macros)
  :short "translate form and clean it up"
  :long "@({

  Examples:
  :tc  (member e a)
  :tc  (list (cadr x) (loop$ for e in lst collect (+ 1 e)))
  :tcp (list (cadr x) (loop$ for e in lst collect (+ 1 e)))
  :tca (list (cadr x) (loop$ for e in lst collect (+ 1 e)))

  General Form:
  :tc form
  :tca form
  :tcp form
  (tc 'form)
  (tca 'form)
  (tcp 'form)
  })

  <p>The @(':')@(tsee trans) command prints the translation of a form into a
  formal term.  However, sometimes the translation can be hard to understand
  because various tags and declarations are included, usually for execution
  efficiency.</p>

  <p>For example, consider @(':trans') versus @(':tcp') of @('(member e a)').</p>

  @({
  ACL2 !>:trans (member e a)

  ((LAMBDA (X L)
     (RETURN-LAST 'MBE1-RAW
                  (MEMBER-EQL-EXEC X L)
                  (RETURN-LAST 'PROGN
                               (MEMBER-EQL-EXEC$GUARD-CHECK X L)
                               (MEMBER-EQUAL X L))))
   E A)

  => *

  ACL2 !>:tcp (member e a)
   (MEMBER-EQUAL E A)
  })

  <p>The @(':tc') command and its variants, @(':tca') and @(':tcp'), translate
  the given form and then ``clean'' it up, returning the result in an @(see
  error-triple).  These commands are especially useful when @(tsee loop$),
  @(see scion)s or @(tsee lambda$) forms are involved in the form to be
  translated.  But they are also useful when @(tsee mbe), @(tsee return-last),
  @(tsee progn$) and other special forms are used or show up in the
  translation.  The @('tc') commands are macros that expand into terms
  involving @(tsee state), since errors are signaled when ill-formed forms are
  submitted.</p>

  <ul>

  <li>@(':tc') <i>form</i> &mdash; translate <i>form</i> and remove everything
    not relevant to the logical value.  This is the logical semantics
    <i>form</i> and is returned in the ``internal format'' of ACL2 terms, i.e.,
    macros have been expanded and all constants are quoted.  The prover will
    reduce <i>form</i> to this term almost immediately.  Typically, this is the
    term that the rewriter will encounter during a proof involving this
    <i>form</i>.  Of course, rewrite rules can further change the form.
    However, see the note below concerning warrants.</li>

  <li>@(':tcp') <i>form</i> &mdash; translate <i>form</i> and remove everything
     not relevant to the logical value as above, and then @(tsee untranslate),
     restoring the use of such system macros as @(tsee lambda$), @(tsee let),
     @(tsee and), @(tsee list), @(tsee cadr), and @(tsee +) and @(tsee *).
     This is the semantics of <i>form</i> in a ``user friendly'' syntax.  The
     suffix ``p'' in @(':tcp') stands for ``pretty.''</li>

  <li>@(':tca') <i>form</i> &mdash; translate <i>form</i> and then
     @('untranslate') as noted above.  This effectively leaves ``annotations''
     in place such as a @('prog2$') joining each @('loop$') in <i>form</i> to
     its semantics, @('declare') forms in @('lambda') objects, and @(tsee let)
     forms associating user variable names to values.  This term is mainly
     meant as a pedagogical device to help you understand how @('loop$')s are
     translated.  The suffix ``a'' in @(':tca') stands for ``annotated.''</li>

  </ul>

  <p>The terms returned by the three flavors of @('tc') are all provably
  equivalent to each other and to the original <i>form</i> provided the
  necessary warrants are assumed.</p>

  <p>For example, if @('sq') is a user-defined function of arity 1 and
  @('(defwarrant sq)') has issued a warrant for @('sq'), then</p>

  @({
  ACL2 !>:tc (loop$ for e in lst collect (sq e))    ; sq is warranted
  (COLLECT$ '(LAMBDA (LOOP$-IVAR) (SQ LOOP$-IVAR))
           LST)
  })

  <p>Nevertheless, the equivalence of the input and output of @(':tc') above
  cannot be proved unless the warrants are assumed.  That is,</p>

  @({
  (thm
    (equal (loop$ for e in lst collect (sq e))
           (COLLECT$ '(LAMBDA (LOOP$-IVAR) (SQ LOOP$-IVAR))
                     LST)))
  })

  <p>will fail with a checkpoint indicating that the warrant for @('sq') must
  be provided.  However,</p>

  @({
  (thm
    (implies (warrant sq)
             (equal (loop$ for e in lst collect (sq e))
                    (COLLECT$ '(LAMBDA (LOOP$-IVAR) (SQ LOOP$-IVAR))
                              LST))))
  })

  <p>succeeds.</p>

  <p>If there is no warrant for @('sq') but there is a badge, then @(':tc') cannot
  clean up the translation because without a warrant the @('lambda') object calling
  @('sq') is not @(see tame).  Thus,</p>

  @({
  ACL2 !>:tc (loop$ for e in lst collect (sq e))   ; sq is badged not warranted
  (COLLECT$ '(LAMBDA (LOOP$-IVAR)
                     (RETURN-LAST 'PROGN
                                  '(LAMBDA$ (LOOP$-IVAR)
                                            (LET ((E LOOP$-IVAR))
                                                 (DECLARE (IGNORABLE E))
                                                 (SQ E)))
                                  ((LAMBDA (E) (SQ E)) LOOP$-IVAR)))
            LST)
  })

  <p>By the way, if you see a quoted @('lambda') objects like that above in
  output from the prover, it probably means the @('lambda') object contains
  unwarranted user-defined symbols!</p>

  <p>The differences between @(':trans') and the three commands (@(':tc'),
  @(':tcp'), and @(':tca')) are perhaps best illustrated by considering their
  respective outputs on a single @(tsee loop$) statement.</p>

  @({
  ACL2 !>:trans (list (cadr x) (loop$ for e in lst collect (+ 1 e)))

  (CONS (CAR (CDR X))
        (CONS (RETURN-LAST
               'PROGN
               '(LOOP$ FOR E IN LST COLLECT (+ 1 E))
               (COLLECT$ '(LAMBDA (LOOP$-IVAR)
                                  (DECLARE (IGNORABLE LOOP$-IVAR))
                                  (RETURN-LAST 'PROGN
                                               '(LAMBDA$ (LOOP$-IVAR)
                                                  (LET ((E LOOP$-IVAR))
                                                    (DECLARE (IGNORABLE E))
                                                    (+ 1 E)))
                                               ((LAMBDA (E) (BINARY-+ '1 E))
                                                LOOP$-IVAR)))
                         LST))
              'NIL))

  => *

  ACL2 !>:tc  (list (cadr x) (loop$ for e in lst collect (+ 1 e)))
   (CONS (CAR (CDR X))
         (CONS (COLLECT$ '(LAMBDA (LOOP$-IVAR)
                                  (BINARY-+ '1 LOOP$-IVAR))
                         LST)
               'NIL))

  ACL2 !>:tcp (list (cadr x) (loop$ for e in lst collect (+ 1 e)))
   (LIST (CADR X)
         (COLLECT$ (LAMBDA$ (LOOP$-IVAR) (+ 1 LOOP$-IVAR))
                   LST))

  ACL2 !>:tca (list (cadr x) (loop$ for e in lst collect (+ 1 e)))
   (LIST (CADR X)
         (PROG2$ '(LOOP$ FOR E IN LST COLLECT (+ 1 E))
                 (COLLECT$ (LAMBDA$ (LOOP$-IVAR)
                                    (LET ((E LOOP$-IVAR))
                                         (DECLARE (IGNORABLE E))
                                         (+ 1 E)))
                           LST)))
  })

  <p>First, notice that @(':trans') also reports the output signature of the
  term but the @(':tc') commands do not.  They all return the cleaned up
  translation in an error triple.  Second, @(':tc') returns a term in the
  internal format: the @('lambda') objects are quoted list constants and their
  bodies are in internal format, e.g., note the @('binary-+') and quoted
  constant @('1') in the output of @(':tc') above.  If you use the @(':tc')
  command on the left-hand side of the conclusion of a @(':rewrite') rule the
  term you see is the term under which the rule is stored, i.e., the rule will
  be tried to rewrite instances of that term.</p>

  <p>The other two commands have ``prettied up'' the output into a more
  user-friendly format.  Third, the @(':tca') command uses a @('prog2$') to
  show the untranslated @('loop$') as a list constant and then show its pretty
  semantics, with a @('let') form in the body of the @('lambda$') reminding you
  that @('loop$-ivar') is what was called @('e').</p>

  <p>It is often helpful to look at the semantics of fancy @('loop$')s.</p>

  @({
  ACL2 !>:tca (loop$ for x in xlst
                     as  y in ylst
                     collect (+ (* a x) (* b y)))
   (PROG2$
       '(LOOP$ FOR X IN XLST AS
               Y IN YLST COLLECT (+ (* A X) (* B Y)))
       (COLLECT$+
            (LAMBDA$ (LOOP$-GVARS LOOP$-IVARS)
                     (DECLARE (XARGS :GUARD (AND (TRUE-LISTP LOOP$-GVARS)
                                                 (EQUAL (LEN LOOP$-GVARS) 2)
                                                 (TRUE-LISTP LOOP$-IVARS)
                                                 (EQUAL (LEN LOOP$-IVARS) 2))))
                     (LET ((A (CAR LOOP$-GVARS))
                           (B (CAR (CDR LOOP$-GVARS)))
                           (X (CAR LOOP$-IVARS))
                           (Y (CAR (CDR LOOP$-IVARS))))
                          (DECLARE (IGNORABLE A B X Y))
                          (+ (* A X) (* B Y))))
            (LIST A B)
            (LOOP$-AS (LIST XLST YLST))))
  })

  <p>Notice what happens to the @(':guard') of the @('lambda$') if we insert
  type specifications with @('of-type').</p>

  @({
  ACL2 !>:tca (loop$ for x of-type (satisfies natp) in xlst
                     as  y of-type integer in ylst
                     collect (+ (* a x) (* b y)))
   (PROG2$
    '(LOOP$ FOR X OF-TYPE (SATISFIES NATP)
            IN XLST AS Y OF-TYPE INTEGER
            IN YLST COLLECT (+ (* A X) (* B Y)))
    (COLLECT$+
     (LAMBDA$ (LOOP$-GVARS LOOP$-IVARS)
              (DECLARE (XARGS :GUARD (AND (TRUE-LISTP LOOP$-GVARS)
                                          (EQUAL (LEN LOOP$-GVARS) 2)
                                          (TRUE-LISTP LOOP$-IVARS)
                                          (EQUAL (LEN LOOP$-IVARS) 2)
                                          (NATP (CAR LOOP$-IVARS))
                                          (INTEGERP (CAR (CDR LOOP$-IVARS))))))
              (LET ((A (CAR LOOP$-GVARS))
                    (B (CAR (CDR LOOP$-GVARS)))
                    (X (CAR LOOP$-IVARS))
                    (Y (CAR (CDR LOOP$-IVARS))))
                   (DECLARE (TYPE (SATISFIES NATP) X)
                            (TYPE INTEGER Y)
                            (IGNORABLE A B X Y))
                   (+ (* A X) (* B Y))))
     (LIST A B)
     (LOOP$-AS (LIST XLST YLST))))
  })

  <p>And notice how the @(':guard') keyword after the @('collect') in the
  @('loop$') statement is added to the @(':guard') of the generated
  @('lambda$').</p>

  @({
  ACL2 !>:tca (loop$ for x of-type (satisfies natp) in xlst
                     as  y of-type integer in ylst
                     collect
                     :guard (and (rationalp a)
                                 (complex-rationalp b))
                     (+ (* a x) (* b y)))
   (PROG2$
    '(LOOP$ FOR X OF-TYPE (SATISFIES NATP)
            IN XLST AS
            Y OF-TYPE INTEGER IN YLST COLLECT :GUARD
            (AND (RATIONALP A)
                 (COMPLEX-RATIONALP B))
            (+ (* A X) (* B Y)))
    (COLLECT$+
     (LAMBDA$
      (LOOP$-GVARS LOOP$-IVARS)
      (DECLARE
        (XARGS :GUARD (AND (TRUE-LISTP LOOP$-GVARS)
                           (EQUAL (LEN LOOP$-GVARS) 2)
                           (TRUE-LISTP LOOP$-IVARS)
                           (EQUAL (LEN LOOP$-IVARS) 2)
                           (NATP (CAR LOOP$-IVARS))
                           (INTEGERP (CAR (CDR LOOP$-IVARS)))
                           (AND (RATIONALP (CAR LOOP$-GVARS))
                                (COMPLEX-RATIONALP (CAR (CDR LOOP$-GVARS)))))))
      (LET ((A (CAR LOOP$-GVARS))
            (B (CAR (CDR LOOP$-GVARS)))
            (X (CAR LOOP$-IVARS))
            (Y (CAR (CDR LOOP$-IVARS))))
           (DECLARE (TYPE (SATISFIES NATP) X)
                    (TYPE INTEGER Y)
                    (IGNORABLE A B X Y))
           (+ (* A X) (* B Y))))
     (LIST A B)
     (LOOP$-AS (LIST XLST YLST))))
  })

  <p>Of course, while these declarations play a role in @(':guard') verification
  and execution in raw Lisp, they are irrelevant to the formal semantics, as made
  clear by @(':tcp').</p>

  @({
  ACL2 !>:tcp (loop$ for x of-type (satisfies natp) in xlst
                     as  y of-type integer in ylst
                     collect
                     :guard (and (rationalp a)
                                 (complex-rationalp b))
                     (+ (* a x) (* b y)))
   (COLLECT$+ (LAMBDA$ (LOOP$-GVARS LOOP$-IVARS)
                       (+ (* (CAR LOOP$-GVARS)
                             (CAR LOOP$-IVARS))
                          (* (CADR LOOP$-GVARS)
                             (CADR LOOP$-IVARS))))
              (LIST A B)
              (LOOP$-AS (LIST XLST YLST)))
  })")
other
(defxdoc tca
  :parents (macros)
  :short "translate a form and clean it up into an annotated pretty term"
  :long "<p>See @(tsee tc).</p>")
other
(defxdoc tcp
  :parents (macros)
  :short "translate a form and clean it up into a pretty term"
  :long "<p>See @(tsee tc).</p>")
other
(defxdoc tenth
  :parents (nth acl2-built-ins)
  :short "Tenth member of the list"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(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.  (Note that ACL2 is case-insensitive when dealing
 with symbols; see @(see symbols).)  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.  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.''  Translation includes
 the process of macroexpansion as well as the replacement of constant symbols
 by their quoted values, while checking 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>Note that translation produces a translated term that need not obey code
 restrictions: a translated term can be used in theorems but might not be
 allowed in definitions (except in @(see non-executable) contexts; see @(see
 defun-nx) and see @(see non-exec)).  Suppose for example that we make the
 following definition, so that @('foo') returns two values (see @(see mv)).</p>

 @({
 (defun foo (x)
   (mv x x))
 })

 <p>Now consider the following translation of a use of @(tsee mv-let).</p>

 @({
 ACL2 !>:trans (mv-let (a b) (foo x) (+ a b))

 ((LAMBDA (MV)
    ((LAMBDA (A B) (BINARY-+ A B))
     (MV-NTH '0 MV)
     (MV-NTH '1 MV)))
  (FOO X))

 => *

 ACL2 !>
 })

 <p>The first definition below is legal.  But the second definition &mdash;
 which uses the translation of the body of the first definition &mdash; is not
 legal.  That's because a @(see lambda) application, as with any function
 application, expects each of its arguments to represent a single value, but
 the argument @('(foo x)') returns two values.</p>

 @({
 (defun legal-def (x)
   (mv-let (a b) (foo x) (+ a b)))

 (defun illegal-def (x)
    ((LAMBDA (MV)
       ((LAMBDA (A B) (BINARY-+ A B))
        (MV-NTH '0 MV)
        (MV-NTH '1 MV)))
     (FOO X)))
 })

 <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>")
other
(defxdoc term-list-listp
  :parents (acl2-built-ins)
  :short "recognizer for a list of @(see clause)s"
  :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 @(see clause) and 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)")
other
(defxdoc term-listp
  :parents (acl2-built-ins)
  :short "recognizer for a list of quotations of terms and of @(see clause)s"
  :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 @(see clause) and 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)")
other
(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 (dx i j) (car (reverse klst))) ,
 })

 <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>")
other
(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>")
other
(defxdoc termify
  :parents (term)
  :short "the process of converting a clause to a term"
  :long "<p>The ACL2 prover represents its goals and subgoals as @(see
  clause)s, e.g., lists of @(see term)s treated as disjunctions.  The
  individual elements of a clause are called <i>literals</i>.  For example a
  goal printed as @('(IMPLIES (AND p q) r)') is internally represented as the
  3-literal clause @('((NOT p) (NOT q) r)').  A clause containing just one
  literal is called a <i>unit clause</i>.</p>

  <p>To <i>termify</i> a clause containing multiple literals, we convert the
  clause to a unit clause using @('IF') to express the disjunction.  For
  example, the 3-literal clause @('((NOT p) (NOT q) r)') is propositionally
  equivalent to the term @('(IF (NOT P) 'T (IF (NOT Q) 'T R))').  By embedding
  that @('IF')-term in a singleton list we obtain a unit clause equivalent to
  the original 3-literal clause.</p>

  <p>Applying an induction scheme to a clause containing multiple literals can
  produce an exponential number of cases.  This does not happen if the clause
  is a unit clause.  So the ACL2 induction mechanism sometimes termifies its
  goal clause before applying the induction scheme to shift the case-analysis
  burden to the rest of the prover.</p>")
other
(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>")
other
(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 @(see 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') @(see 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-recursive 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 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 !>
 })")
other
(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)")
other
(defxdoc the
  :parents (guard compilation acl2-built-ins)
  :short "Special form for execution efficiency or run-time type checks"
  :long "<p>@('THE') is a Common Lisp special form.  It is usually used as a
 way to boost performance 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.  When
 evaluating code directly in the top-level loop or in @(':')@(tsee logic)-mode
 functions that have not been @(see guard)-verified, @('THE') can perform
 run-time type 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.  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>A term of the form @('(the double-float <term>)') will assist ACL2's syntax
 checking by telling ACL2 that @('<term>') returns a df.  See @(see df) for
 relevant background.</p>

 <p>@('THE') is defined in Common Lisp.  See any Common Lisp documentation for
 more information.</p>")
other
(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>")
other
(defxdoc the-number
  :parents (numbers acl2-built-ins)
  :short "Coerce an expected number to a number"
  :long "<p>Like @(tsee fix), @('the-number') logically returns its argument
 unchanged if that argument is numeric and @('0') otherwise.  Unlike @('fix'),
 the @(see guard) for @('(the-number x)') is @('(acl2-numberp x)'), and
 @('(the-number x)') evaluates to @('x') in raw Lisp (see @(see
 guards-and-evaluation) for relevant discussion).</p>

 @(def the-number)")
other
(defxdoc the-true-list
  :parents (true-listp acl2-built-ins)
  :short "Coerce an expected true list to a true list"
  :long "<p>Like @(tsee true-list-fix), @('the-true-list') logically returns
 its argument unchanged if that argument satisfies @(tsee true-listp) and
 otherwise returns a corresponding ``fixed'' true list.  Unlike
 @('true-list-fix'), the @(see guard) for @('(the-true-list x)') is
 @('(true-listp x)'), and @('(the-true-list x)') evaluates immediately to
 @('x') in raw Lisp (see @(see guards-and-evaluation) for relevant
 discussion).</p>

 @(def the-true-list)")
other
(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)
      (:rewrite car-cons)
      (:elim car-cdr-elim)} .
 })

 <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 to @('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 (concatenate 'string str "-PACKAGE")
 "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>")
other
(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 iff length))

 ACL2 Warning [Theory] in ( IN-THEORY (DISABLE ...)):  The :DEFINITION
 rules for the built-in functions MV-NTH and IFF are disabled by the
 theory expression (DISABLE MV-NTH IFF LENGTH), but some expansions
 of their calls may still occur.  See :DOC theories-and-primitives.
 })

 <p>This warning is telling us that the built-in functions @(tsee mv-nth) and
 @(tsee iff) are given certain special handling, hence their calls may be
 expanded even when their definitions are disabled.  This behavior applies to
 the functions in the list obtained by evaluating the constant,
 @('*definition-minimal-theory*').</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:  18

 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 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 the built-in function SYMBOLP is disabled by the
 theory expression (DISABLE (:E SYMBOLP)), but 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 4268)
 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, which are
 the respective values of built-in constants @('*definition-minimal-theory*')
 and @('*built-in-executable-counterparts*').</p>

 @(def *definition-minimal-theory*)

 @(def *built-in-executable-counterparts*)

 <p>A third 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>

 <p>We conclude with a note for advanced users only.  You can eliminate all
 special treatment discussed above for expanding the definition of @(tsee
 mv-nth) (but not for any of the other primitives listed above) by evaluating
 the following form (also see @(see defattach-system)).</p>

 @({
 (defattach-system simplifiable-mv-nth-p constant-nil-function-arity-0)
 })

 <p>That said, this is probably only useful for very specific cases of
 ``system-level'' programming.  You can restore the default behavior as
 follows.</p>

 @({
 (defattach-system simplifiable-mv-nth-p constant-t-function-arity-0)
 })")
other
(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>")
other
(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>")
other
(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>")
other
(defxdoc third
  :parents (nth acl2-built-ins)
  :short "Third member of the list"
  :long "<p>See any Common Lisp documentation for details.</p>")
other
(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 store an
 event; it merely causes the theorem prover to attempt a proof.  But like
 @('defthm'), calls of @('thm') are legal in event contexts (see @(see
 embedded-event-form)).</p>

 @({
  General Form:
  (thm term
       :instructions instructions
       :hints        hints
       :otf-flg      otf-flg)
 })

 <p>where @('term') is a term alleged to be a theorem, and @(tsee
 instructions), @(tsee hints), and @(tsee otf-flg) are as described in the
 corresponding @(see documentation) topics.  The keyword arguments are
 optional.</p>

 <p>For information on how @('thm') is implemented using @(tsee make-event),
 see @(see make-event-example-3).</p>")
other
(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 gcl) to return to the ACL2
 @(see command) loop after an interrupt, type @(':')@(tsee q).  To continue
 (resume) after an interrupt (in gcl), type @(':r').  To cause an interrupt 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>")
other
(defxdoc time$
  :parents (programming acl2-built-ins)
  :short "Time the evaluation of a given form"
  :long "<p>Semantically, @('(time$ x ...)') equals @('x').  However, its
 evaluation writes timing output to the trace output (which is usually the
 terminal), as explained further below.</p>

 <p>Note: Some of the functionality below is available only for certain host
 Common Lisp implementations.</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>")
other
(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 @(see 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>")
other
(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 @(see 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 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)
 })")
other
(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).</p>")
other
(defxdoc toggle-inhibit-er
  :parents (output-controls errors)
  :short "Add or delete an error output string from the @('inhibit-er-table')"
  :long "<p>See @(see set-inhibit-er) for relevant background.</p>

  @({
  General Form:
  (toggle-inhibit-er string)
  })

  <p>where @('string') is the name of some error output like @('"Translate"')
  or @('"Failure"').</p>

  <p>Note: This is an event!  It does not print the usual event @(see 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 toggle-inhibit-er!) for a corresponding non-@(tsee
  local) event.  Indeed, @('(toggle-inhibit-er str)') is equivalent to
  @('(local (toggle-inhibit-er! str))').</p>

  <p>The given string is added to the list of strings used for inhibiting error
  output if it is not there already and is deleted from the list if it is
  there.  Case is unimportant in @('string').  See @(tsee
  set-inhibit-er).</p>")
other
(defxdoc toggle-inhibit-er!
  :parents (output-controls errors)
  :short "Toggle an @('inhibit-er-table') entry non-@(tsee local)ly"
  :long "<p>Please see @(see toggle-inhibit-er), which is the same as
 @('toggle-inhibit-er!') except that the latter is not @(tsee local) to
 the @(tsee encapsulate) or the book in which it occurs.  Probably @(see
 toggle-inhibit-er) 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>")
other
(defxdoc toggle-inhibit-warning
  :parents (output-controls)
  :short "Add or delete a warning string from the @('inhibit-warnings-table')"
  :long "@({
  General Form:
  (toggle-inhibit-warning string)
  })

  <p>where @('string') is the name of some warning like @('"Subsume"'),
  @('"Non-rec"') or @('"Rewrite-lambda-object"').</p>

  <p>Note: This is an event!  It does not print the usual event @(see 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 toggle-inhibit-warning!) for a corresponding non-@(tsee
  local) event.  Indeed, @('(toggle-inhibit-warning str)') is equivalent to
  @('(local (toggle-inhibit-warning! str))').</p>

  <p>The given string is added to the list of inhibited warnings if it is not
  there already and is deleted from the list if it is there.  Case is
  unimportant in @('string').  See @(tsee set-inhibit-warnings).</p>")
other
(defxdoc toggle-inhibit-warning!
  :parents (output-controls)
  :short "Toggle an @('inhibit-warnings-table') entry non-@(tsee local)ly"
  :long "<p>Please see @(see toggle-inhibit-warning), which is the same as
 @('toggle-inhibit-warning!') except that the latter is not @(tsee local) to
 the @(tsee encapsulate) or the book in which it occurs.  Probably @(see
 toggle-inhibit-warning) 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>")
other
(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>")
other
(defxdoc top
  :parents nil
  :short "ACL2 documentation (system only, not including the community books)"
  :long "<p>This is the documentation for the ACL2 system.  For the ACL2+Books
  Manual, which documents both the ACL2 system and the ACL2 @(see
  community-books), see the @(`(:raw (combined-manual-ref))`).</p>")
other
(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>

 <p>Since the defined function @('top-level') takes only @('state') as a
 parameter, the given form should not include any user-defined @(see stobj)s
 that occur free in the form.</p>

 <p>Finally, note that since @('top-level') runs a function that is defined in
 @(':')@(tsee program) mode, it is possible for a raw lisp error to occur.
 Here is an example.</p>

 @({
 ACL2 !>(top-level (car 3))

 ***********************************************
 ************ ABORTING from raw Lisp ***********
 ********** (see :DOC raw-lisp-error) **********
 Error:  The value 3 is not of the expected type LIST.
 While executing: CAR
 ***********************************************
 })")
other
(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>")
other
(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 !>
 })")
other
(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 <see topic='@(url
 acl2-sedan)'>ACL2s</see>, 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 trace-co).</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, as described below, to the @('trace') utility of the
 underlying Common Lisp.</p>

 <p>@(':COND'), @(':ENTRY'), and @(':EXIT')</p>

 <h3>Introduction</h3>

 <p>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>

 <h3>Available Variables</h3>

 <blockquote>NOTE.  The symbols mentioned below, for example @('ARGLIST'), are
 all in the @('"ACL2"') package.  If you are in another package you may need
 an @('"ACL2::"') package prefix, e.g., @('ACL2::ARGLIST').</blockquote>

 <p>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)').  Finally, the variable @('TRACE-LEVEL') will
 be bound to the level, or depth, of tracing; that is, the number printed at
 entry and exit (e.g., 3 in @('`3>'') and @('`<3'')).  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>

 <h3>Basic Options</h3>

 <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 !>
 })

 <h3>Advanced Options (alphabetical list)</h3>

 <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 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
 @(':multiplicity') option is ignored.  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 to the trace utility of 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.  Note that @(see stobj)s will be printed as vectors (rather than
 their usual hiding with symbols such as @('<st>')) when using
 @(':evisc-tuple :print'), but other structures will still be hidden unless
 @(':hide nil') is supplied.</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).
 (For an exception regarding stobjs, see the discussion of @(':evisc-tuple
 :print') above.)  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') and
 @(':multiplicity') options).  Each trace spec generates its own call of Lisp
 @('trace'): directly in most cases, but if SBCL is the host Lisp then the SBCL
 @('trace') syntax is accommodated by placing the the function symbol last,
 after any keyword options.  A trust tag (see @(see defttag)) is required in
 order to use the @(':native') option, because arbitrary raw Lisp may be
 executed by the options!</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.  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!  (But it may accept many options that are not available with the
 non-native ACL2 @('trace$').)</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.
 (But see Remark (0) below for an exception involving @(see invariant-risk).)
 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>

 <h3>Remarks</h3>

 <p>(0) For a @(':')@(tsee program) mode function with @(see invariant-risk),
 recursive calls are never traced.  To see these recursive calls, use one of
 the two methods to defeat invariant-risk checking; see @(see
 invariant-risk). (Implementation note: This behavior on recursive calls is a
 consequence of how ACL2 defines the executable-counterpart &mdash; also known
 as the ``*1* function'' (see @(see evaluation)) &mdash; to call a local
 function to do the computation.)</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>")
other
(defxdoc trace-co
  :parents (io acl2-built-ins)
  :short "The @(see trace) character output channel"
  :long "<p>See @(see io) for relevant background.  @('(Trace-co state)') is an
 open character output channel.  @(csee Trace) output is printed to this
 channel.  Evaluate @('(set-trace-co CHAN state)') to set @('(Trace-co state)')
 to the channel, @('CHAN').</p>

 <p>``Trace-co'' stands for ``trace character output.'' The initial value of
 @('trace-co') is the same as the value of @(tsee *standard-co*).</p>")
other
(defxdoc trans
  :parents (macros)
  :short "Print the translation of a form"
  :long "@({
  Examples:
  :trans (list a b c)
  :trans (caddr x)
  :trans (cond (p q) (r))
 })

 <p>ACL2 accepts user-level syntax as input, and it prints the result of
 <i>translating</i> it to an internal syntax.  This translation includes
 macroexpansion, replacing @(tsee let) forms by @(tsee lambda) expressions,
 quoting constants, and so on.  See @(see term) for relevant background.  The
 printing can be abbreviated, as it uses the @(':term') @(see evisc-tuple)
 (with a @('flg') of @('nil'), hence without any abbreviation by default; see
 @(see set-evisc-tuple)).</p>

 <p>Note that the @('trans') command prints a @(tsee term) that need not obey
 code restrictions: that term can be used in theorems but might not be allowed
 in definitions (except in @(see non-executable) contexts; see @(see defun-nx)
 and see @(see non-exec)).</p>

 <p>@('Trans') takes one argument, an alleged term in user syntax, and
 translates it, expanding the macros in it completely.  Either an error is
 caused or the internal syntax for the term (representing its formal meaning)
 is printed.  It also prints 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.  See @(see trans*) for a command that
 can show intermediate expansion results.</p>

 <p>The argument supplied to @(':trans') may contain variables, including @(see
 stobj) names.  However, variables that are not stobj names are assumed not to
 be dfs (see @(see df)).  For example, @(':trans (df+ x y)') causes an error;
 to see the desired translation use @(':trans! (df+ x y)').</p>

 <p>It is sometimes more convenient to use @(':')@(tsee trans1), which, unlike
 @(':trans'), only does top-level macroexpansion.</p>

 <p>For more, see @(see term).</p>")
other
(defxdoc trans!
  :parents (macros)
  :short "Print the translation without code restrictions on the input"
  :long "@({
  Examples:
  :trans! (list a b c)
  :trans! (append x state)
  :trans! (cons (mv 3 4) x)
 })

 <p>@(':Trans!') is identical to @(':')@(tsee trans), except that @(':trans!')
 is more permissive: it allows expressions that may occur in theorems but are
 illegal in code.  In particular, @(':trans!') allows violations of
 single-threadedness and multiple-value restrictions.  Thus, the second and
 third forms above are legal for @(':trans!') even though they are illegal for
 @(':trans').  Also see @(see trans), see @(see trans1), and see @(see
 trans*).</p>")
other
(defxdoc trans*
  :parents (macros)
  :short "Show intermediate expansion results for the translation of a form"
  :long "<p>See @(see term) for background on translated and untranslated
 terms.  See @(see trans), @(see trans!), and @(tsee trans1) for other
 utilities that expand and translate their input.</p>

 <p>Unlike @('trans'), the @('trans*') command can print not only the
 translation of a given expression but also the intermediate expansions leading
 to that translation, and @('trans*') can also print @(tsee make-event)
 expansions.  Another difference between @('trans*') and @('trans') is that
 @('trans*') does not enforce code restrictions; thus, multiple-value
 mismatches and violations of single-threadedness are permitted by @('trans*').
 That is: when @('trans*') takes steps to convert an untranslated term to a
 translated term, it does so as though one is translating a theorem statement,
 not a definition body.</p>

 <p>But like @('trans'), the @('trans*') command prints @(tsee term)s that need
 not obey code restrictions: they can be used in theorems but might not be
 allowed in definitions (except in @(see non-executable) contexts; see @(see
 defun-nx) and see @(see non-exec)).  Also like @('trans'), the printing uses
 the @(':term') @(see evisc-tuple) (with a @('flg') of @('nil'), hence without
 any abbreviation by default; see @(see set-evisc-tuple)).</p>

 <p>For discussion of how one may use a keyword command like @(':trans*') in
 place of calling the corresponding utility, in this case @('trans*'), see
 @(see keyword-commands).  Below we focus on the use of the keyword command,
 @(':trans*').</p>

 <p>We begin with some simple examples that may suffice to explain how to use
 @('trans*').  We then document this utility before concluding with further
 details.</p>

 <h3>Introductory Examples</h3>

 <p>The examples below assume that the following definition has been
 submitted.</p>

 @({
 (defmacro mac (x y) `(append ,y (rest ,x)))
 })

 <p>Here is a log showing a typical use of @(':trans*'); comments are
 below.</p>

 @({
 ACL2 !>:trans* t (mac u v)

 Iteration 1 produces (by expansion):
 (APPEND V (REST U))
 ----------

 Iteration 2 produces (by expansion):
 (BINARY-APPEND V (REST U))
 ----------

 Iteration 3 produces (by translation):
 (BINARY-APPEND V (CDR U))
 ----------
 ACL2 !>
 })

 <p>We see that Iteration 1 expands away the call of the macro, @('mac').  The
 next iteration expands away the resulting call of the macro, @('append').
 Those two steps are labeled with &ldquo;(by expansion)&rdquo; because they are
 removing top-level macro calls.  The result of the second iteration is not a
 macro call, so @(':trans*') finishes up by translating that result to obtain
 the final result; notice translation of the second argument of the
 @('binary-append') call by expanding @(tsee rest) to @(tsee cdr).</p>

 <p>The example above illustrates a couple of aspects of @(':trans*').</p>

 <ul>

 <li>An expansion step occurs only with a top-level macro call.</li>

 <li>A translation step is always last.</li>

 </ul>

 <p>The result is the same for input @(':trans* 3 (mac u v)'), i.e., if first
 argument @('t') is replaced by @('3') or, in fact, any integer that is at
 least the total number of iterations produced with argument @('t').  But we
 can specify that we want to stop before the final step.  One way is to specify
 a number less than the number of iterations.  Here is what we get when we
 specify that we should stop after 1 iteration.</p>

 @({
 ACL2 !>:trans* 1 (mac u v)

 Iteration 1 produces (by expansion):
 (APPEND V (REST U))
 ----------
 ACL2 !>
 })

 <p>Another way to stop early is to rule out the final translation step.  Here
 is an example by using @('nil') or a negative integer as the first
 argument.</p>

 @({
 ACL2 !>:trans* -5 (mac u v) ; same for nil, -2, -3, -4, etc. instead of -5

 Iteration 1 produces (by expansion):
 (APPEND V (REST U))
 ----------

 Iteration 2 produces (by expansion):
 (BINARY-APPEND V (REST U))
 ----------
 ACL2 !>
 })

 <p>If you are only interested in obtaining the final result, with no
 intermediate printing, put parentheses around the first argument.  Here is
 what happens when we make that modification to the example immediately
 above.</p>

 @({
 ACL2 !>:trans* (-5) (mac u v) ; same answer for nil, -2, -3, etc instead of -5
  (BINARY-APPEND V (REST U))
 ACL2 !>
 })

 <p>Note the single space of indentation in the result above.  That indicates
 that what is actually returned is multiple values, @('(mv nil (BINARY-APPEND V
 (REST U)) state)').  Without the parentheses, @('(mv nil :invisible state)')
 is returned.  See @(see error-triple).</p>

 <h3>Documentation</h3>

 @({
  General Forms:
  :trans t form
  :trans nil form
  :trans n form
  :trans -n form
  :trans (x) form ; for x = t, nil, n, or -n
 })

 <p>where @('n') is a positive integer and @('form') is any ACL2 expression
 (i.e., any untranslated term; see @(see term)).  These commands repeat
 translation steps as described later below, according to the value of the
 first argument, as follows.</p>

 <ul>

 <li>@('t'): iterate to completion, printing intermediate results</li>

 <li>@('nil'): iterate to completion except for skipping the final translation
 step, printing intermediate results</li>

 <li>@('n'): iterate at most @('n') steps, printing intermediate results</li>

 <li>@('-n'): iterate at most @('n') steps except for skipping a final
 translation step, printing intermediate results</li>

 <li>@('(x)'): same as @('x') but without printing intermediate results, and
 returning an @(see error-triple) @('(mv nil val state)') where @('val') is the
 final result,</li>

 </ul>

 <p>It is reasonable to think of a first argument of @('t') as
 &ldquo;infinity&rdquo; and of @('nil') as &ldquo;minus infinity&rdquo;.
 Although a first argument of @('(t)') is much like using @(tsee trans), key
 differences besides enforcement of code restrictions (as discussed above) are
 that @('trans*') performs @(tsee make-event) expansion and discards certain
 &ldquo;wrappers&rdquo; like @(tsee with-output), as described below.  The
 related utility @(tsee trans*-) differs from @('trans*') in only one way:
 @('trans*-') does not perform @('make-event') expansion.</p>

 <p>Here is a specification of the iteration step performed on a given form,
 which is initially the second argument of @('trans*') and is updated by each
 iteration.  If the form is not a true-list then iteration halts without any
 further result.  Otherwise the form may be written as a call @('(caller arg1
 ... argk)'), and the next step's result, if any, depends on @('caller') as
 follows.</p>

 <ul>

 <li>If @('caller') is in the list of &ldquo;event wrappers&rdquo;,
 @(`*destructure-expansion-wrappers*`), then the next step's result is the last
 argument of the call, denoted @('argk') above.</li>

 <li>Else if @('caller') is @(tsee make-event), the result is the form's
 @('make-event') expansion.  (This step is skipped when @(tsee trans*-) is used
 rather than @('trans*').)</li>

 <li>Else if @('caller') is a built-in event constructor such as @(tsee defun)
 or @(tsee defthm), or one of @(tsee certify-book), @(tsee defpkg), or @(tsee
 in-package), then iteration is halted.
 (Technical note: The actual test used here is whether @('caller') is a key of
 the alist value of the constant, @('*syms-not-callable-in-code-fal*').)</li>

 <li>Else if @('caller') is a macro, expand the macro call.</li>

 <li>Otherwise translate the form, except that as noted above, if the first
 argument of @('trans*') is @('nil') or a negative integer, then this step is
 skipped and instead iteration is halted.</li>

 </ul>

 <h3>Further Details</h3>

 <p>While @('trans*') will almost always determine accurately how the given
 input expands and is ultimately translated, it is not quite 100% reliable for
 that purpose.  In particular, @('make-event') expansion isn't guaranteed to
 check that the expansion is an embedded event form, as is required for @(tsee
 make-event).  Another limitation for @('make-event') expansion is that when an
 iteration reaches the form @('(:OR ev1 ... evk)'), the iteration concludes
 rather than evaluating the events @('evi') (see @(see make-event)).</p>

 <p>A similar utility, @(tsee trans*-), stops iteration at a call of
 @('make-event') without continuing with its @('make-event') expansion.  That
 is, in fact, the only difference between @('trans*') and @('trans*-').</p>

 <p>We conclude by adding emphasis to an aspect of @('trans*') that is already
 noted above: expansion (whether macroexpansion or @('make-event') expansion)
 and elimination of event wrappers only take place for the top-level call, not
 calls occurring in subterms.  Of course, one can call @('trans*') on subterms.
 Consider the following example.</p>

 @({
 ACL2 !>:trans* t (defund-nx f (x) x)

 Iteration 1 produces (by expansion):
 (WITH-OUTPUT
      :STACK
      :PUSH :OFF
      :ALL
      (PROGN (ENCAPSULATE NIL
               (LOGIC)
               (SET-STATE-OK T)
               (WITH-OUTPUT :STACK :POP
                            (DEFUND F (X)
                              (DECLARE (XARGS :NON-EXECUTABLE T :MODE :LOGIC))
                              (PROG2$ (THROW-NONEXEC-ERROR 'F (LIST X))
                                      X)))
               (WITH-OUTPUT :STACK :POP :OFF
                            SUMMARY (IN-THEORY (DISABLE (:E F)))))
             (WITH-OUTPUT :STACK :POP :OFF SUMMARY
                          (VALUE-TRIPLE '(:DEFUND-NX F)))))
 ----------

 Iteration 2 is dropping the WITH-OUTPUT wrapper:
 (PROGN (ENCAPSULATE NIL
          (LOGIC)
          (SET-STATE-OK T)
          (WITH-OUTPUT :STACK :POP
                       (DEFUND F (X)
                         (DECLARE (XARGS :NON-EXECUTABLE T :MODE :LOGIC))
                         (PROG2$ (THROW-NONEXEC-ERROR 'F (LIST X))
                                 X)))
          (WITH-OUTPUT :STACK :POP :OFF
                       SUMMARY (IN-THEORY (DISABLE (:E F)))))
        (WITH-OUTPUT :STACK :POP :OFF
                     SUMMARY (VALUE-TRIPLE '(:DEFUND-NX F))))
 ----------
 ACL2 !>
 })

 <p>One can then call @('trans*') on the @(tsee defund) subterm to see its
 expansion.</p>")
other
(defxdoc trans*-
  :parents (macros)
  :short "Variant of @(tsee trans*) the skips @(tsee make-event) expansion"
  :long "<p>See @(see trans*).  The only difference between @('trans*') and
  @('trans*-') is that the latter does not do @(tsee make-event) expansion, but
  rather, stops the iterations when reaching a form that is a call of
  @('make-event').</p>")
other
(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 @(see multiple-value)
 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) may have modified the user stobj ST.  See
 :DOC user-stobjs-modified-warning.

 (4 <state> <st>)
 ACL2 !>
 })

 <p>These warnings indicate a potentially serious violation of applicative
 semantics when one is also updating user-defined stobjs outside calls of
 @('trans-eval')!  To understand and perhaps avoid such warnings, see @(see
 user-stobjs-modified-warnings).  Also see @(see
 trans-eval-and-locally-bound-stobjs) for discussion of how @('trans-eval')
 modifies global stobj values, not locally-bound stobjs.</p>")
other
(defxdoc trans-eval-and-locally-bound-stobjs
  :parents (trans-eval stobj)
  :short "@(tsee Trans-eval) deals in global @(see stobj)s."
  :long "<p>This topic assumes familiarity with the relatively advanced
 utility, @(tsee trans-eval).  In particular, see @(see trans-eval-and-stobjs)
 for relevant background.  It may also be helpful to see @(see
 user-stobjs-modified-warnings).</p>

 <p>A stobj may be locally bound by @(tsee stobj-let) or @(tsee
 with-local-stobj).  But @(tsee trans-eval) ignores such local bindings!  The
 following example illustrates this point.</p>

 @({
 (defstobj st fld)

 (defun f (x state)
   (declare (xargs :stobjs state :mode :program))
   (with-local-stobj
     st
     (mv-let (state local-fld st)
       (mv-let (erp val state)
         (trans-eval `(update-fld ',x st) 'f state nil)
         (declare (ignore erp val))
         (mv state (fld st) st))
       (mv state local-fld))))

 ; The following returns (<state> NIL).  Thus, the return value of local-fld
 ; indicated above, which is the value of the fld of the locally-bound st, is
 ; nil: trans-eval did not update the locally-bound stobj!
 (f 3 state)

 ; On the other hand the global stobj, st, was indeed updated by the call of f
 ; just above.
 (assert-event (equal (fld st) 3))
 })

 <p>Here is another such example, this time using @(see nested-stobjs) instead
 of @(tsee with-local-stobj).</p>

 @({
 (defstobj sub1 sub1-fld1)
 (defstobj top1 (top1-fld :type sub1))

 (defun g (x top1 state)
   (declare (xargs :stobjs (top1 state) :mode :program))
   (stobj-let
    ((sub1 (top1-fld top1))) ; bindings
    (sub1 state)             ; producer variables
    (mv-let (erp val state)  ; producer

 ; NOTE: The reference to sub1 inside the following trans-eval call is actually
 ; a reference to the global sub1 from the user-stobj-alist, not to the sub1
 ; bound by stobj-let above.  Thus, this trans-eval call updates the global
 ; stobj, sub1, not the locally bound sub1 that is a field of top1.

            (trans-eval `(update-sub1-fld1 ',x sub1) 'g state t)
            (declare (ignore erp val))
            (mv sub1 state))
    (mv top1 state)          ; consumer
   ))

 (g 7 top1 state)
 ; The global stobj, sub1, has been updated by the call of g just above.
 (assert-event (equal (sub1-fld1 sub1) 7))

 (g 8 top1 state)
 ; The global stobj, sub1, has been updated by the call of g just above.
 (assert-event (equal (sub1-fld1 sub1) 8))

 ; Obtain the sub1 field of top1.
 (defun get-sub1-of-top1 (top1)
   (declare (xargs :stobjs top1 :mode :program))
   (stobj-let
    ((sub1 (top1-fld top1)))  ; bindings
    (val)                     ; producer variable
    (sub1-fld1 sub1)          ; producer
    val                       ; consumer
   ))

 ; The calls of g above did not update the locally bound sub1.
 ; That is, they did not update the sub1 field of top1.
 (assert-event (equal (get-sub1-of-top1 top1) nil))
 })")
other
(defxdoc trans-eval-and-stobjs
  :parents (trans-eval stobj)
  :short "How user-defined @(see stobj)s are handled by @(tsee trans-eval)"
  :long "<p>See @(see trans-eval) for basic background on the relatively
 advanced system utility, @('trans-eval').  In this topic we discuss how
 @('trans-eval') handles user-defined @(see stobj)s.</p>

 <p>A field of the ACL2 @(see state), the @('user-stobj-alist'), is an
 association list (alist) that maps each user-defined @(see stobj) name to its
 current value.  @('Trans-eval') evaluates with respect to this alist, so that
 any time a variable (which must be a stobj name) is to be evaluated, its value
 is looked up in that alist.</p>

 <p>For example, suppose that you evaluate the following forms in the top-level
 ACL2 loop.</p>

 @({
 (defstobj st fld)
 (fld st)
 })

 <p>To evaluate the expression, @('(fld st)'), ACL2 calls @(tsee trans-eval)
 &mdash; or more accurately its variant, @(tsee trans-eval-default-warning)
 &mdash; on that expression.  (We generally consider all such variants to be
 the same as @('trans-eval') for purposes of this documentation topic.)
 Although @('st') has the syntax of a global variable, it is bound in the
 @('user-stobj-alist').  Here we see @('trans-eval') in action.</p>

 @({
 ACL2 !>(trace$ trans-eval-default-warning)
  ((TRANS-EVAL-DEFAULT-WARNING))
 ACL2 !>(fld st)
 1> (TRANS-EVAL-DEFAULT-WARNING (FLD ST)
                                TOP-LEVEL |*the-live-state*| T)
 <1 (TRANS-EVAL-DEFAULT-WARNING NIL ((NIL))
                                |*the-live-state*|)
 NIL
 ACL2 !>
 })

 <p>This call of @('trans-eval') (or more accurately,
 @('trans-eval-default-warning')) invokes an ACL2 evaluator @('(ev form alist
 state ...)'), by calling it on the form @('(fld st)') and an alist that binds
 the variable @('st') to its value in the @('user-stobj-alist') component of
 the ACL2 @(see state).  We may refer to this value as the ``global value of''
 @('st').</p>

 <p>We can of course update this stobj.</p>

 @({
 ACL2 !>(update-fld 3 st)
 1> (TRANS-EVAL-DEFAULT-WARNING (UPDATE-FLD 3 ST)
                                TOP-LEVEL |*the-live-state*| T)
 <1 (TRANS-EVAL-DEFAULT-WARNING NIL ((ST) . REPLACED-ST)
                                |*the-live-state*|)
 <st>
 ACL2 !>(fld st) ; check that the update occurred
 1> (TRANS-EVAL-DEFAULT-WARNING (FLD ST)
                                TOP-LEVEL |*the-live-state*| T)
 <1 (TRANS-EVAL-DEFAULT-WARNING NIL ((NIL) . 3)
                                |*the-live-state*|)
 3
 ACL2 !>
 })

 <p>We see above that the global value of @('st') was indeed updated by
 evaluating the @('update-fld') call.  That is: the value of @('st') in the
 @('user-stobj-alist') of the ACL2 @(tsee state) was updated by calling @(tsee
 trans-eval) on the expression, @('(update-fld 3 st)').  More generally: as
 @('trans-eval') returns, it updates the @('user-stobj-alist') of the ACL2
 @(see state) according to all stobj values that have been returned.</p>")
other
(defxdoc trans1
  :parents (macros)
  :short "Print the one-step macroexpansion of a form"
  :long "<p>See @(see term) for background on translated and untranslated terms,
 including some discussion of macros.</p>

 @({
  Examples:
  :trans1 (list a b c)
  :trans1 (caddr x)
  :trans1 (cond (p q) (r))
 })

 <p>This utility takes one argument, an alleged untranslated 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>

 <p>On very rare occasions, complete translation is not quite the same as
 translating the output of @(':trans1'), though the two should still be
 logically equivalent.  This can happen for a call of @(tsee stobj-let) in the
 body of a function: its translation may include a check for duplicate indices
 that is omitted in the single-step macroexpansion.</p>")
other
(defxdoc translam
  :parents (apply$)
  :short "Print the translation of a lambda$ expression"
  :long "@({
  :translam (lambda$ (x) (+ 1 x))
  :translam (lambda (x) (+ 1 x))
  })

  <p>This function takes a @('lambda$') term or an unquoted @('LAMBDA')
  constant.  In the former case, it translates the @('lambda$') and prints the
  result.  In the latter case it puts the @('LAMBDA') in a @('QUOTE') and
  translates it as though it occurred in a @(':FN') slot.  Unless an error is
  signaled it prints the same @('LAMBDA') object as the result.</p>

  <p>This utility exists because you cannot write, say,</p>

  @({
  :trans (lambda$ (x) (+ 1 x))
  })

  <p>because the @('trans') utility assumes its argument in an ordinary (ilk
  @('NIL')) slot.  In such slots, @('lambda$') terms are disallowed and no
  restrictions are enforced on quoted @('LAMBDA') objects.</p>

  <p>This utility is useful for seeing what the formal translation of a
  @('lambda$') term is.  For example,</p>

  @({
  ACL2 !>:translam (lambda$ (x)
                            (declare (type (satisfies natp) x))
                            (* x x))
  })

  <p>produces the quoted well-formed @('LAMBDA') expression:</p>

  @({
  '(LAMBDA (X)
           (DECLARE (TYPE (SATISFIES NATP) X)
                    (XARGS :GUARD (NATP X) :SPLIT-TYPES T)
                    (IGNORABLE X))
           (RETURN-LAST 'PROGN
                        '(LAMBDA$ (X)
                                  (DECLARE (TYPE (SATISFIES NATP) X))
                                  (* X X))
                        (BINARY-* X X)))
  })

  <p>You might now have an inkling about why we discourage you from trying to
  enter quoted well-formed @('LAMBDA') objects by hand!  The normal form of a
  quoted well-formed @('LAMBDA') object is complicated so that @('apply$') can
  rapidly identify the parts, generate guard conditions, compile the object,
  recognize objects coming from @('lambda$') terms, etc.</p>")
other
(defxdoc transparent-functions
  :parents (meta)
  :short "Working around restrictions on the use of evaluators in meta-level rules"
  :long "<p>See @(see evaluator-restrictions) for relevant background.  For
 examples of the use of transparent functions, see @(see community-book) file
 @('books/system/tests/transparent-functions-input.lsp'), with corresponding
 output in file @('transparent-functions-log.txt') in the same directory.</p>

 <p>A function is called a &ldquo;transparent function symbol&rdquo; when it is
 declared with @(':transparent t') in a @(see signature) of an @(tsee
 encapsulate) event.  By thus declaring a function to be transparent, you are
 modifying the notion of &ldquo;ancestor&rdquo; of a meta-level function as
 follows, for purposes of the ancestor restriction described in @(see
 evaluator-restrictions): when a transparent function @('f') has an attachment
 @('g') (see @(see defattach)), then @('g') is the sole ancestor (supporter) of
 @('f').</p>

 <p>We illustrate with a (contrived) example, which shows how declaring a
 function to be transparent can avoid an error.  Consider what happens when we
 submit the following events in a fresh ACL2 session.</p>

 @({
 (defstub f0 (x) t)

 (encapsulate
   (((f1 *) => *)
    ((f2 *) => *))
   (local (defun f1 (x) (f0 x)))
   (local (defun f2 (x) (f0 x)))
   (defthm f2-is-f1
     (implies (f0 x)
              (equal (f2 x) (f1 x)))
     :rule-classes nil))

 (defn g0 (x) x)

 (defattach f0 g0)

 (with-output :off :all ; avoid noisy output
   (defevaluator evl evl-list
     ((f0 x))))

 (defn meta-fn1 (x)
   (if (f1 x)
       x
     x))

 (defattach (f1 consp) (f2 consp))

 (defthm thm1
   (equal (evl x a)
          (evl (meta-fn1 x) a))
   :rule-classes ((:meta :trigger-fns (nth))))
 })

 <p>The final (@(tsee defthm)) event results in the following error.</p>

 @({
 ACL2 Error in ( DEFTHM THM1 ...):  The proposed :META rule, THM1, is
 illegal because the attached function F0 is ancestral in both the evaluator
 and meta functions.  See :DOC evaluator-restrictions and see :DOC transparent-
 functions.

 The following is an ancestor path from F0 to the meta function META-FN1,
 i.e., each function symbol is a supporter of the next:

 (F0 F1 META-FN1)

 The following is an ancestor path from F0 to the evaluator function
 EVL, i.e., each function symbol is a supporter of the next:

 (F0 EVL)
 })

 <p>The events above make it clear that the alleged ancestor paths are indeed
 ancestor paths, in the sense that each function symbol in the path occurs in
 the definition or @(see constraint) for the function symbol immediately after
 it.</p>

 <p>To avoid this error, we need to arrange that @('f0') is no longer a common
 ancestor of @('meta-fn1') and @('evl').  The notion of ancestor doesn't change
 for the path leading to the evaluator function; but for the path leading to
 the meta function, a transparent function symbol has its attachment as its
 ancestor instead of the function symbols in its @(see constraint).  In
 particular, @('f1') normally has @('f0') as an ancestor, since @('f0') occurs
 in the constraint on @('f1'); but if @('f1') is transparent and has an
 attachment, then its attachment is the sole ancestor of @('f0'), as though
 @('f1') had been defined to be @('f0').  Thus, if we replace the @(tsee
 encapsulate) event in our example simply by declaring its @(see signature)
 functions to be transparent, as follows, then the error disappears.</p>

 @({
 (encapsulate
   (((f1 *) => * :transparent t)
    ((f2 *) => * :transparent t))
   (local (defun f1 (x) (f0 x)))
   (local (defun f2 (x) (f0 x)))
   (defthm f2-is-f1
     (implies (f0 x)
              (equal (f2 x) (f1 x)))
     :rule-classes nil))
 })

 <p>We close with some restrictions pertaining to transparent function
 symbols.</p>

 <ul>

 <li>If any function is declared with @(':transparent t') in the signatures of
 an @('encapsulate') event, then all must be.</li>

 <li>If any function is declared with @(':transparent t') in the signatures of
 an @('encapsulate') event, then every signature in a superior or inferior
 @('encapsulate') event must also specify @(':transparent t').</li>

 <li>The value of the @(':transparent') keyword in a signature must be @('t')
 or the default, @('nil').</li>

 <li>The signatures of a @(tsee partial-encapsulate) (or of any encapsulate
 with a call of @('set-unknown-constraints-supporters')) must not specify
 @(':transparent t') in its signatures.</li>

 <li>When a @(tsee defattach) event attaches to a transparent function symbol
 @('f'), that event must attach to every function symbol constrained in an
 encapsulate with @('f'), and only to such function symbols.  The same holds
 for unattaching in place of attaching.</li>

 </ul>")
other
(defxdoc true-list-fix
  :parents (true-listp acl2-built-ins)
  :short "Coerce to a true list"
  :long "<p>Many functions that process lists follows the <b>true-list-fix
 convention</b>: whenever @('f') is given some non-@(tsee true-listp) @('x')
 where it expected a list, that is, some @('x') with a non-@('nil') @(tsee
 final-cdr), it will act as though it had been given @('(true-list-fix x)')
 instead.  As a few examples, logically,</p>

 <ul>
 <li>@('(endp x)') ignores the final @('cdr') of @('x')</li>
 <li>@('(len x)') ignores the final @('cdr') of @('x')</li>
 <li>@('(append x y)') ignores the final @('cdr') of @('x') (but not
 @('y'))</li>
 <li>@('(member a x)') ignores the final @('cdr') of @('x')</li>
 </ul>

 <p>@('True-list-fix') is often useful when writing theorems about how
 list-processing functions behave.  For example, it allows us to write strong,
 hypothesis-free theorems such as:</p>

 @({
     (equal (character-listp (append x y))
            (and (character-listp (true-list-fix x))
                 (character-listp y)))
 })

 <p>Indeed, @('true-list-fix') is the basis for @(see list-equiv), an extremely
 common @(see equivalence) relation.</p>

 <p>Efficiency note.  In practice, most lists are @('nil')-terminated.  As an
 optimization, @('true-list-fix') tries to avoid any consing by first checking
 whether its argument is a @(see true-listp), and, in that case, it simply
 returns its argument unchanged.</p>

 <p>For a logically equivalent utility that returns its argument unchanged
 (with no checking) during normal evaluation, see @(see the-true-list).</p>

 @(def true-list-fix-exec)

 @(def true-list-fix)")
other
(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)")
other
(defxdoc true-listp
  :parents (lists acl2-built-ins)
  :short "Recognizer for proper (@('nil')-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)")
other
(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)")
other
(defxdoc trust-mfc
  :parents (extended-metafunctions)
  :short "A macro that supports testing of extended metafunctions)"
  :long " @({
 Example Form:
 (trust-mfc (mfc-ts term mfc state))

 General Form:
 (trust-mfc form)
 })

 <p>where @('form') is any form, but is typically a call of an extended
 metafunction such as @('mfc-ts') or @('mfc-rw').</p>

 <p>Extended metafunctions (see @(see extended-metafunctions)) may
 normally only be invoked during proofs.  @('Trust-mfc') is an advanced utility
 that relaxes that requirement, thus supporting the testing of
 extended-metafunctions outside calls of the ACL2 prover.  When you use
 @('trust-mfc'), you are taking on the responsibility to pass only well-formed
 @(tsee mfc) arguments to your calls of extended-metafunctions, since otherwise
 raw Lisp errors may be signaled.  Because of this danger, the logical
 definition of @('trust-mfc') causes an error, thus making it useless at the
 top level and in @(':')@(tsee logic)-mode code:</p>

 @(def trust-mfc)

 <p>However, @('trust-mfc') can be very useful when used in @(':')@(tsee
 program)-mode code that calls extended metafunctions, which makes it useful
 for @(':logic')-mode code as well; see @(see program-wrapper).  The log below
 illustrates typical usage.</p>

 @({
 ACL2 !>(defun my-mfc (state)
          ;; Define a simple metafunction-contextx.
          (declare (xargs :mode :program :guard t :stobjs state))
          (make metafunction-context
                :rdepth 10000
                :type-alist nil
                :obj '?
                :geneqv nil
                :wrld (w state)
                :fnstack nil
                :ancestors nil
                :backchain-limit nil
                :simplify-clause-pot-lst nil
                :rcnst (initial-rcnst-from-ens (ens state) (w state) state nil)
                :gstack nil
                :ttree nil
                :unify-subst nil))

 Summary
 Form:  ( DEFUN MY-MFC ...)
 Rules: NIL
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
  MY-MFC
 ACL2 !>(mfc-ts '(cons x y) (my-mfc state) state) ; error: not in prover


 Meta-level function Problem:  This error can quite possibly be avoided;
 see :DOC trust-mfc.  You or some meta-level function applied MFC-TS
 but not from within the theorem prover's meta-level function handler.
 This suggests you are trying to test a meta-level function and have
 evidently manufactured an allegedly suitable context.  Perhaps so.
 But that is so difficult to check that we don't bother.  Instead we
 cause this error and urge you to test your meta-level function by having
 the meta-level function handler invoke it as part of a test proof-
 attempt. To do this, assume the metatheorem that you intend eventually
 to prove.  You may do this by executing the appropriate DEFTHM event
 embedded in a SKIP-PROOFS form.  Then use THM to submit conjectures
 for proof and observe the behavior of your metafunction.  Remember
 to undo the assumed metatheorem before you attempt genuine proofs!
 If this suggestion isn't applicable to your situation, contact the
 authors.



 ACL2 Error in TOP-LEVEL:  ACL2 cannot ev the call of non-executable
 function MFC-TS on argument list:

 ((CONS X Y) MFC STATE)

 To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.

 ACL2 !>(trust-mfc (mfc-ts '(cons x y) (my-mfc state) state)) ; top-level (bad)


 HARD ACL2 ERROR in TRUST-MFC:  It is illegal to run TRUST-MFC except
 in raw Lisp, typically by way of a :program-mode function body.  See
 :DOC trust-mfc.  Evaluation of the form
 (TRUST-MFC (MFC-TS '(CONS X Y) (MY-MFC STATE) STATE)) has led to this
 error.



 ACL2 Error in TOP-LEVEL:  Evaluation aborted.  To debug see :DOC print-
 gv, see :DOC trace, and see :DOC wet.

 ACL2 !>(defun my-mfc-ts (term mfc state)
          (declare (xargs :mode :program :stobjs state))
          (trust-mfc (mfc-ts term mfc state)))

 Summary
 Form:  ( DEFUN MY-MFC-TS ...)
 Rules: NIL
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
  MY-MFC-TS
 ACL2 !>(my-mfc-ts '(cons x y) (my-mfc state) state)
 3072
 ACL2 !>(decode-type-set 3072) ; let's see that the result above is reasonable
 *TS-CONS*
 ACL2 !>
 })")
other
(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>")
other
(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>")
other
(defxdoc ttree
  :parents (miscellaneous)
  :short "Tag-trees"
  :long "<p>Many low-level ACL2 functions take and return ``tag trees'' or
 ``ttrees'' (pronounced ``tee-trees'') which contain useful information such as
 the lemmas used, the linearize assumptions made, etc.  Here we present only
 minimal user-level information, for example in support of the use of the @(see
 break-rewrite) utility or writing metafunctions.  Implementation-level
 information about tag trees may be found in the Developer's Guide; users
 should probably not visit <see topic='@(url developers-guide-utilities)'>that
 topic</see> unless they plan to become ACL2 developers.</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.</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>")
other
(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>")
other
(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>")
other
(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.  It was updated in December, 2024 (from the original version of
 about two decades ago) thanks to Andrei Koltsov, to work with recent ACL2
 versions.</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.
 Documentation is available for the growing collection of @(see
 community-books) that are typically downloaded with ACL2, and a mailing list,
 @('acl2-help'), is available (see the <a
 href='http://www.cs.utexas.edu/users/moore/acl2/'>ACL2 home page</a>.  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   1  (INCLUDE-BOOK "data-structures/alist-defthms"
                            :DIR ...)
              
              [Included books, outermost to innermost:
               ".../acl2/books/data-structures/alist-defthms.lisp"
               ".../acl2/books/data-structures/alist-defuns.lisp"
              ]
              
    >V d       (DEFUN
                BINDING (X A)
                "The value bound to X in alist A."
                (DECLARE
                   (XARGS :GUARD (AND (ALISTP A)
                                      (OR (EQLABLEP X) (EQLABLE-ALISTP A)))))
                (CDR (ASSOC 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).  If
 we submit @(':pe assoc') then we can see that @('assoc') is a macro that
 essentially serves as an abbreviation for the primitive function @(tsee
 assoc-equal).  We say no more about @('assoc') here but instead focus on
 @('assoc-equal').  If we use @(':pe') to look at the definition of @(tsee
 assoc-equal):</p>

 @({
    PV    -8489  (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, our attempt to prove it failed with the following subgoal
 under a top-level induction.</p>

 @({
    Subgoal *1/4''
    (IMPLIES (AND (CONSP BK)
                  (NOT (EQUAL NM (CAR (CAR BK))))
                  (NOT (BOUND?-EQUAL NM (CDR BK)))
                  (BOUND?-EQUAL NM BK))
             (EQUAL (REMBIND-EQUAL NM (BIND-EQUAL NM PNUM (CDR BK)))
                    (REMBIND-EQUAL NM (CDR BK))))
 })

 <p>We have defined @('del-phone') using @('rembind'), and @('change-phone')
 using @('in-book') (which uses @('bound?')) and @('bind'); but we have
 ``equal'' suffixes in the subgoal.  The cause is theorems of the form
 @('***->***-equal'), which are given in the included book.  We can use @(see
 history)'s @(':')@(tsee pl) command to print the rules for a given name or
 term.  Here is the part of @(':')@(tsee pl)'s output we are interested in now,
 for the @('rembind') function:</p>

 @({
    ACL2 !>:pl rembind
    ...

    Rune:         (:REWRITE REMBIND->REMBIND-EQUAL)
    Enabled:      T
    Hyps:         T
    Equiv:        EQUAL
    Lhs:          (REMBIND X A)
    Rhs:          (REMBIND-EQUAL X A)
    Backchain-limit-lst: NIL
    Subclass:     ABBREVIATION

    ...
 })

 <p>We can see that @(see rewrite) rule @('rembind->rembind-equal') is @(see
 enable)d and that it replaces <i>lhs</i> with <i>rhs</i>.  For functions
 @('bind'), @('binding') and @('bound?') we have similar rules.</p>

 <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-equal-bind-equal
      (equal (rembind-equal nm (bind-equal nm pnum bk))
             (rembind-equal 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-equal-bind-equal') 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-equal')
 and @('bind-equal') that wasn't supplied with the alists theory. Hopefully,
 such omissions will be rare.</p>

 <p>Let's take two steps back now (just enter the @(':u') command twice) to get
 acquainted with a method that will be very useful to us.  What happens if we
 state the previous lemma another way?</p>

 @({
    (defthm rembind-bind
      (equal (rembind name (bind name num book))
             (rembind name book)))
 })

 <p>An attempt to prove @('del-change') would fail then with the same subgoal
 as above.  In this case we can give to the prover the hint to use
 @('rembind-bind') as an instance of @('del-change') (see @(see hints) and find
 keywords @(':use') and @(':instance')):</p>

 @({
    (defthm del-change-lemma-instance-example
      (equal (del-phone nm (change-phone nm pnum bk))
             (del-phone nm bk))
      :hints (("Goal" :use (:instance rembind-bind
                                      (name nm)
                                      (num pnum)
                                      (book bk)))))
 })

 <p>As described in @(see hints), a @(':use') hint causes the prover to replace
 a goal @('G') with new goal (@('IMPLIES') @('P') @('G')), where @('P') is the
 specified theorem to use.  The @(':instance') form specifies instantiation of
 the free variables of a previously proved theorem.  See @(see lemma-instance)
 for more information on this subject.</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 ensure 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?-equal))))

    (defthm find-phone-pnump
      (implies (and (phonebookp bk)
                    (in-book? nm bk))
               (pnump (find-phone nm bk)))
      :hints (("Goal" :in-theory (enable bound?-equal
                                         binding-equal))))
 })

 <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?-equal') and @('binding-equal') 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?-equal') and
 @('binding-equal') and hope that by opening up these functions, the
 conjectures will reduce to versions that the prover does know enough about,
 perhaps using proof 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 and any subgoals of it.</p>

 <p>It's important to understand that it's not enough to @(see enable) the
 @('bound?') and @('binding') functions.  That's because rewrite rules of the
 form @('***->***-equal') (mentioned above) will replace @(see enable)d
 functions with @(see disable)d ones for which there are not sufficient rules
 to complete the proof.  We can use @(see history)'s very informative command
 @(':')@(see pl) to get a lot of information about rules for a given name.</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.  Perhaps you will use the instantiation of lemmas method,
 described above.  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-equal
      (implies (and (not (equal x y))
                    (not (member-equal x (strip-cars a))))
               (not (member-equal x (strip-cars (bind-equal y z a))))))

    (defthm bind-equal-preserves-domain-setp
      (implies (and (alistp bk)
                    (setp (domain bk)))
               (setp (domain (bind-equal nm num bk))))
      :hints (("Goal" :in-theory (enable domain))))
 })

 <p>Let's take two steps back (using @(':u') twice) and prove the following
 instead of @('member-equal-strip-cars-bind-equal'):</p>

 @({
    (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))))))
 })

 <p>Then @('bind-equal-preserves-domain-setp') fails:</p>

 @({
    Subgoal *1/5''
    (IMPLIES (AND (CONSP BK)
             (NOT (EQUAL NM (CAR (CAR BK))))
             (SETP (STRIP-CARS (BIND-EQUAL NM NUM (CDR BK))))
             (CONSP (CAR BK))
             (ALISTP (CDR BK))
             (NOT (MEMBER-EQUAL (CAR (CAR BK))
                                (STRIP-CARS (CDR BK))))
             (SETP (STRIP-CARS (CDR BK))))
        (NOT (MEMBER-EQUAL (CAR (CAR BK))
                           (STRIP-CARS (BIND-EQUAL NM NUM (CDR BK))))))
 })

 <p>We can use a @(see lemma-instance) to prove it:</p>

 @({
    (defthm bind-equal-preserves-domain-setp
      (implies (and (alistp bk)
                    (setp (domain bk)))
               (setp (domain (bind-equal nm num bk))))
      :hints (("Goal" :in-theory (enable domain))
              ("Subgoal *1/5''" :use (:instance
                                      member-equal-strip-cars-bind
                                      (x (car (car bk)))
                                      (y nm)
                                      (z num)
                                      (a (cdr bk))))))
 })

 <p>The use of @(see lemma-instance) is somewhat artificial in this example,
 but this method gives great opportunities to lead ACL2 in proving theorems.
 That said, it is generally preferable to avoid @(':use') hints in favor of
 developing a useful set of @(see rewrite) rules, since those rules can help
 to automate future proof attempts.</p>

 <p>We continue now with proofs that our operations preserve the
 @('phonebook'') invariant.</p>

 @({
    (defthm phonebookp-alistp
      (implies (phonebookp bk)
               (alistp bk)))

    (defthm bind-equal-preserves-phonebookp
      (implies (and (phonebookp bk)
                    (namep nm)
                    (pnump num))
               (phonebookp (bind-equal nm num 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-equal))))

    (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-equal))))

    (defthm member-remove-equal
      (implies (and (not (equal a b))
                    (not (member a x)))
               (not (member a (remove-equal b x)))))

    (defthm remove-equal-preserves-setp
      (implies (setp l)
               (setp (remove-equal x l))))

    (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-equal 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?-equal x a))
                    (alistp a))
               (equal (strip-cdrs (bind-equal x y a))
                      (append (strip-cdrs a) (list y))))
      :hints (("Goal" :in-theory (enable bound?-equal))))

    (defthm member-append
      (iff (member e (append x y))
           (or (member e x)
               (member e y))))

    (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-equal
      (implies (and (not (member-equal z (strip-cdrs a)))
                    (not (equal z y)))
               (not (member-equal z (strip-cdrs
                                     (bind-equal 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))))
 })")
other
(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))))
 })")
other
(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>")
other
(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; also see @(see type-reasoning) for additional relevant
background.</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 &ldquo;<see topic='@(url
type-reasoning)'>type reasoning</see>&rdquo; 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 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; see @(see type-reasoning) for relevant basic background...</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>")
other
(defxdoc type-alist
  :parents (type-set)
  :short "An ACL2 representation of contextual knowledge"
  :long "<p>See @(see type-reasoning) for basic background on type reasoning in
  ACL2.</p>

  <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>")
other
(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.  Also see @(see
 type-reasoning) for basic background on type reasoning in ACL2.</p>

 <p>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 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>")
other
(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 @(see 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 <see topic='@(url
 type-reasoning)'>type reasoning</see> knows that @('f') returns a
 Boolean.</p>")
other
(defxdoc type-reasoning
  :parents (rule-classes)
  :short "ACL2 reasoning with &ldquo;types&rdquo;"
  :long "<p>ACL2 has a &ldquo;type reasoning&rdquo; system, which may be viewed
 as a relatively basic 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)?'', &ldquo;does this
 expression produce a non-@('nil') value (i.e., is it true)?&rdquo;, etc.  This
 system uses built-in reasoning about types, for example that a rational number
 is not a cons; when the ACL2 prover reports that a goal is simplified using
 &ldquo;primitive type reasoning&rdquo;, it is referring to such built-in type
 reasoning.  However, type reasoning is also driven by @(see type-prescription)
 rules, as we'll discuss shortly.</p>

 <p>ACL2 reasoning, including type reasoning, takes place with respect to a
 context that associates terms with values that represent their
 &ldquo;types&rdquo;.  These contexts are called @(see type-alist)s, and those
 values are called @(see type-set)s; however, unless you write certain
 sophisticated tools, perhaps such as @(see clause-processor)s, you probably do
 not need to know more than that about these two notions.  (If you're curious
 about them, you can see @(see type-set) and see @(see type-alist).)  For
 example, when ACL2 attempts to prove a conjecture @('(implies (and (p
 x) (integerp (f x))) (p2 x))'), it builds a type-alist recording that @('(p
 x)') and @('(integerp (f x))') are true when attempting to reason about @('(p2
 x)').  That type-alist associates @('(p x)') with a value representing the
 complement of the set, @('{nil}'), meaning that @('(p x)') is non-@('nil'),
 i.e., true.  But for @('(integerp (f x))') something a bit more clever takes
 place: since @('integerp') recognizes a Boolean combination of built-in types
 &mdash; see @(see compound-recognizer) &mdash; the context associates @('(f
 x)') with a value representing the set of integers.  So for example, type
 reasoning can conclude from that type-alist that @('(not (consp (f x)))') is
 true, since the built-in types for integer and cons are disjoint.</p>

 <p>As noted above, type reasoning can take advantage of @(see
 type-prescription) rules.  In short, such a rule tells ACL2 that any instance
 of the &ldquo;typed-term&rdquo; of the rule must have a specified type.  To
 relieve the hypotheses of type-prescription rules, the type-reasoning 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 are represented rather
 explicitly in the context in which the question is posed.  Consider the
 following example from the @(see type-prescription) documentation.</p>

 @({
  (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)
 })

 <p>It may seem impossible to relieve the hypothesis @('(character-listp lst)')
 by type reasoning, since there is no suitable &ldquo;type&rdquo; for @('lst'),
 i.e., @('character-listp') does not recognize a Boolean combination of ACL2
 types (see @(see compound-recognizer)).  However, suppose we are attempting to
 prove a theorem of the form @('(implies (and (character-listp x) p) q)') and
 ACL2 is in the process of simplifying either @('p') or @('q').  In that case,
 the context &mdash; that is, the type-alist &mdash; will associate the term
 @('(character-listp x)') with a value indicating that this term is true, i.e.,
 non-@('nil').  Then if ACL2 encounters the term @('(nth k x)'), it will try to
 apply the type-prescription rule above, matching @('k') to @('n') and matching
 @('lst') to @('x').  The instantiated first hypothesis of that rule will then
 be @('(character-listp x)').  Since the type-alist designates
 @('(character-listp x)') as true, that hypothesis is successfully relieved.
 Again, there was no @('character-listp') &ldquo;type&rdquo; involved; what was
 typed was the entire term, @('(character-listp x)').</p>

 <p>The instantiated hypothesis above was relieved because it was in the
 context, so no rewriting was necessary to establish it.  See @(see force) for
 how to involve the ACL2 rewriter to establish hypotheses of type-prescription
 rules.</p>")
other
(defxdoc type-set
  :parents (miscellaneous)
  :short "How type information is encoded in ACL2"
  :long "<p>See @(see type-reasoning) for basic background on type reasoning in
 ACL2.</p>

 <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*           ;;; nil-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 two's-complement bitwise @('`not'') 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 bitwise @('`not'') 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 !>
 })")
other
(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.  Also see @(see
 type-reasoning) for basic background on type reasoning in ACL2.</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>")
other
(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>

 <p>While type specs may be used in @(see defstobj) events, the @('HASH-TABLE')
 and @('STOBJ-TABLE') type specs may only be used in those events.  We say
 nothing further about them in the present topic.</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)
  DOUBLE-FLOAT           (DFP X) ; See :DOC df.
  INTEGER                (INTEGERP X)
  (INTEGER i j)          (AND (INTEGERP X)   ; See notes below.
                              (<= i X)
                              (<= X j))
  LIST                   (LISTP X)
  (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)
  NUMBER                 (ACL2-NUMBERP x)
  (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-CHAR-P 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 supports a richer set of type specifiers than ACL2
 supports.</p>")
other
(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))
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
  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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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.  The first command below,
 @(':set-gag-mode nil'), instructs ACL2 to supply its full prover output;
 normally that output is restricted considerably (``gagged''), but we include
 it all below in support of the associated explanations.</p>

 <p><img src='res/tours/green-line.gif'></img></p>

 <code>
 ACL2!&gt;<b>:set-gag-mode nil</b>
 &lt;state&gt;
 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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(defxdoc tours
  :parents (|Pages Written Especially for the Tours| acl2-tutorial)
  :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>")
other
(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>")
other
(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>")
other
(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)').
 Note that @(':ubt!') will not print error messages.</p>

 <p>@(':')@(tsee Oops) will undo the last @(':ubt!').  See @(see ubt), @(see
 ubt?), @(see ubu!), @(see ubu), @(see ubu?), and @(see u).</p>")
other
(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>")
other
(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>")
other
(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>")
other
(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)'). Note that @(':ubu!') will not print error messages.</p>

 <p>@(':')@(tsee Oops) will undo the last @(':ubu!').  Also see @(see ubu),
 @(see ubu?), @(see ubt), @(see ubt!), @(see ubt?), and @(see u).</p>")
other
(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>")
other
(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>")
other
(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>")
other
(defxdoc uncertified-books
  :parents (books)
  :short "Invalid @(see certificate)s and uncertified @(see books)"
  :long "<p>For relevant background see @(see books), see @(see books-tour),
 see @(see certificate), and see @(see portcullis).</p>

 <p>You may have been led to this topic by a warning or error message such as
 the following.</p>

 @({
 There is no certificate on file for /u/smith/foo.lisp.  See :DOC
 uncertified-books.
 })

 <p>The remedy is to <i>certify</i> the indicated book; see @(see
 certify-book).  Such certification is typically a <i>very</i> good idea, as
 discussed further below.  After certification succeeds, the book will have a
 valid @(see certificate) and the message will no longer be printed.  The rest
 of this topic explains issues pertaining to books that are <i>uncertified</i>,
 that is, have not been certified.</p>

 <p>@(tsee Include-book) has a special provision for dealing with an
 uncertified book, i.e., a file whose @(see certificate) is missing or
 invalid (e.g., one for a different ACL2 version or whose @(see book-hash)
 value describes a file other than the one actually read).  In this case, a
 warning is printed (as above) and the book is usually processed much as though
 it were certified.

 If a book @('B.lisp') was previously certified, it will probably have a
 corresponding file @('B.port') representing the @(see portcullis) @(see
 command)s for that previous certification.  (See keyword argument
 @(':write-port') of @(tsee certify-book).)  Then if @('B.lisp') is currently
 uncertified and @('B.port') exists, evaluation of @('(include-book "B")')
 will cause the forms in @('B.port') to be evaluated before the forms in
 @('B.lisp').  To avoid such evaluation for @('.port') files, see @(see
 compilation).</p>

 <p>The ability to include uncertified @(see books) is handy but it 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>")
other
(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 !>
 })")
other
(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>")
other
(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>")
other
(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>")
other
(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).  These are both legal @(see event) forms.
 Note: These events do not affect memoization from @(tsee memoize) events that
 either are derived from calls of @(tsee memoize-partial) or have a
 non-@('nil') value of @(tsee memoize) argument @(':invoke')</p>")
other
(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.  See @(see monitor).</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 @('rune').  We simply check that @('rune') is currently
 monitored and remove it.  If @('rune') corresponds to no entry on the list of
 monitored runes we cause an error since it may indicate a misspelling.</p>")
other
(defxdoc unquote
  :parents '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 !>
 })")
other
(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>")
other
(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)")
other
(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>

 <p>When executing calls of @(tsee hons-get) in parallel, you may see messages
 about @('"Fast alist discipline"') violations.  This can happen because each
 thread uses its own underlying hash table for fast access by @('hons-get'),
 but typical top-level calls of @(tsee hons-acons) and @(tsee make-fast-alist)
 only affect that main thread's hash table.  You can use
 @('(set-slow-alist-action nil)') to eliminate this warning entirely; see @(see
 slow-alist-warning).</p>")
other
(defxdoc unsupported-waterfall-parallelism-features
  :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) and @(tsee with-brr-data) utilities are 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>

 <p>During proofs with @(see waterfall-parallelism) enabled, you may see
 messages about @('"Fast alist discipline"') violations, even when using
 @(tsee hons-get) appropriately.  This can happen because each thread uses its
 own underlying hash table for fast access by @('hons-get'), but typical
 top-level calls of @(tsee hons-acons) and @(tsee make-fast-alist) only affect
 that main thread's hash table.  You can use @('(set-slow-alist-action nil)')
 to eliminate this warning entirely; see @(see slow-alist-warning).</p>")
other
(defxdoc untouchable
  :parents (defttag)
  :short "Function symbols and state globals that cannot be referenced"
  :long "<p>Untouchables are functions 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).  Macros can be made
 effectively untouchable as well; see @(see defmacro-untouchable).</p>")
other
(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>")
other
(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>")
other
(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>")
other
(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)")
other
(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)")
other
(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') states that its argument is a
 character.</p>

 <p>@('Upper-case-p') is a Common Lisp function.  See any Common Lisp
 documentation for more information.  Note that the value returned may depend
 on the host Lisp; see @(see soundness), specifically Example 1 in the Section,
 &ldquo;Examples of divergence among Lisp implementations&rdquo;.</p>

 @(def upper-case-p)")
other
(defxdoc useless-runes
  :parents (certify-book accumulated-persistence)
  :short "Speed up proofs by disabling useless @(see rune)s"
  :long "<p>This topic documents the @(':useless-runes') keyword argument of
 @(tsee certify-book) and @(tsee ld), which makes it possible to speed up
 repeated running of a book's @(see events).  This option is ignored in
 ACL2(r) (see @(see real)) and, when @(see waterfall-parallelism) is active, in
 ACL2(p) (see @(see parallelism)).</p>

 <h3>Introduction</h3>

 <p>For a given @(see event), the so-called ``useless'' rules are those that do
 not contribute to the progress of any proof supporting that event.  For more
 background see @(see accumulated-persistence), which is typically used for
 finding rules (or more precisely, @(see rune)s) to @(see disable) during
 proofs.  The feature described in the present topic provides automation for
 the discovery and effective disabling of useless rules.</p>

 <p>Below, we focus first on the use of @(':useless-runes') for @(tsee
 certify-book) rather than for @(tsee ld).  The main time to use this option
 with @(tsee ld) may be when developing a book that is to be certified
 eventually with a @(':useless-runes') option.  We return to discuss @('ld')
 later in this topic (in Section ``Modifications for @(tsee ld)'').</p>

 <p>To use the @(':useless-runes') option of @(tsee certify-book), first
 certify your book &mdash; say, @('foo.lisp') &mdash; by supplying option
 @(':useless-runes :write').  This creates a file in the subdirectory @('.sys')
 of the book's directory, creating that directory if it does not already exist.
 This new file, @('.sys/foo@useless-runes.lsp'), associates names of @(tsee
 defthm), @(tsee defun), and @(tsee verify-guards) @(see events) with sets of
 ``useless'' @(see rune)s'': rule names (``@(see rune)s'') not contributing to
 the progress of the proof.  Then, future certifications can use option
 @(':useless-runes :read') &mdash; or some limited variations of @(':read')
 using numeric values, as discussed below) &mdash; which, during evaluation of
 an event, will effectively @(see disable) rules associated with that event in
 file @('foo@useless-runes.lsp').</p>

 <p>Environment variable @('ACL2_USELESS_RUNES') can take the value
 @('"write"') or @('"read"') to be used in place of the @(':useless-runes')
 option @(':read') or @(':write') (respectively) of @('certify-book').
 @('ACL2_USELESS_RUNES') can also have value @('"nil"') (case-insensitive) or
 a string representing a legal numeric value for the @(':useless-runes') option
 of @(tsee certify-book).  This is all discussed below.</p>

 <p>By default, certification of the @(see community-books), when using either
 @('make') (as described elsewhere; see @(see books-certification)) or @(see
 build::cert.pl), is performed with environment variable
 @('ACL2_USELESS_RUNES') set to @('"-25"').  This setting, for each book
 @('foo.lisp'), causes part of the corresponding file
 @('.sys/foo@useless-runes.lsp'), if it exists, to be consulted as described
 below.  However, useless runes are entirely ignored (both their use and for
 writing to @('.sys/foo@useless-runes.lsp') files) both in ACL2(r) (see @(see
 real)) and, when @(see waterfall-parallelism) is active, in ACL2(p) (see @(see
 parallelism)).</p>

 <h3>Detailed Documentation</h3>

 <p>Again, the @(':useless-runes') option provides a way to automate discovery
 and, in subsequent uses, disabling of useless runes that can speed up proofs.
 Information about useless runes is communicated using a file, which we call
 the ``@useless-runes.lsp file'' (or, sometimes, ``useless-runes file''), whose
 name is obtained by adding the suffix @('"@useless-runes.lsp"') to the book
 name, and which is placed in the @('.sys') subdirectory of the book's
 directory, after creating that subdirectory if it does not already exist.  For
 example, if the book's filename is @('"foo.lisp"') then the corresponding
 @useless-runes.lsp has filename @('".sys/foo@useless-runes.lsp"').</p>

 <p>The following table summarizes the legal values for the option
 @(':useless-runes'); further explanation follows.</p>

 @({
 :write   ; Write the @useless-runes.lsp file to speed up future proofs.
 :read or ; Read the @useless-runes.lsp file to speed up proofs;
 :read?   ;   file must exist for :read, but need not exist for :read?.
 N, -N    ; N is a positive integer not exceeding 100.  Then |N|% of the rules
          ;   indicated by the @useless-runes.lsp file are to be kept disabled.
          ;   The @useless-runes.lsp file needs to exist for N but not for -N.
 nil      ; Do not read or write the @useless-runes.lsp file.
 })

 <p>Notice in particular that @(':useless-runes 100') is equivalent to
 @(':useless-runes :read'), while @(':useless-runes -100') is equivalent to
 @(':useless-runes :read?').</p>

 <p>The option @(':useless-runes :write') directs that a corresponding
 @useless-runes.lsp file is to be written.  Each top-level entry of this file
 that is non-trivial (see below) has the form</p>

 @({
 (name
  (frames-1 tries-1 rune-1)
  (frames-2 tries-2 rune-2)
  ...
  (frames-k tries-k rune-k)
  )
 })

 <p>where @('name') is the name of a @(tsee defthm), @(tsee defun), or @(tsee
 verify-guards) event, and each tuple @('(frames-i tries-i rune-i)') indicates
 the number of frames and tries for @('rune-i') recorded for the proofs done on
 behalf of that event.  ACL2 claims that none of the indicated rules
 contributed to the progress of the proof.  See @(see accumulated-persistence),
 but also see @(see accumulated-persistence-subtleties) for some limitations.
 These top-level entries are listed in order of event in the book, from top to
 bottom.  Because of @(see local) @(see events), the same name may appear more
 than once; we say more about this in the ``Subtleties'' section, below.</p>

 <p>Note that ``trivial'' entries are possible, where there are no tuples; in
 that case, just @('(name)') is printed, on a single line.  Otherwise printing
 uses the format shown above, where the first line contains a left parenthesis
 on the left margin followed by the name, and each tuple is on a single line
 starting in column 1 (i.e., after a single space), as is the final right
 parenthesis.</p>

 <p>The option @(':useless-runes :read') or @(':useless-runes :read?') directs
 use of the corresponding @useless-runes.lsp file, if it exists.  If that file
 does not exist, an error is caused when the option value is @(':read') but the
 option is simply ignored when the option value is @(':read?').</p>

 <p>The value of @(':useless-runes') may also be a non-zero integer between
 -100 and 100, inclusive.  The absolute value of this number is the percentage
 of the runes associated with the current event that are to be effectively kept
 @(see disable)d, starting with the useless rune with the highest number of
 frames built (see @(see accumulated-persistence)).  For example, if the value
 is 20 then 1/5 of the runes associated with the current event in the
 @useless-runes.lsp file are to be kept disabled; so if the relevant top-level
 form in that file is</p>

  @({
 (name
  (frames-1 tries-1 rune-1)
  (frames-2 tries-2 rune-2)
  (frames-3 tries-3 rune-3)
  (frames-4 tries-4 rune-4)
  (frames-5 tries-5 rune-5)
  (frames-6 tries-6 rune-6)
  (frames-7 tries-7 rune-7)
  )
 })

 <p>then 1/5 of the 7 runes are to be disabled, so since the first integer
 greater than or equal to 7/5 is 2, the runes @('rune-1') and @('rune-2') will
 be kept disabled.  Note again that the value @('100') for @(':useless-runes')
 gives the same behavior as the value @(':read'), and the value @('-100') gives
 the same behavior as the value @(':read?').</p>

 <p>The @(':useless-runes') option need not be given explicitly to @(tsee
 certify-book).  Suppose that the environment variable @('ACL2_USELESS_RUNES')
 has a non-empty value.  Then that value implicitly invokes the
 @(':useless-runes') option as indicated by the following table, which shows
 how that environment variable value corresponds to a value for the
 @(':useless-runes') option.</p>

 @({
 ACL2_USELESS_RUNES value          :useless-runes value
 ------------------------          --------------------

 WRITE (case insensitive)          :write
 READ (case insensitive)           :read
 READ? (case insensitive)          :read?
 i, ij, -i, -ij, 100, -100         corresponding integer, which cannot be 0
   (i and j are base-10 digits)
 })

 <p><b>Important</b>.  An explicitly supplied @(':useless-runes') value
 normally takes priority over the value of environment variable
 @('ACL2_USELESS_RUNES').  However, for @('certify-book') the environment
 variable takes priority if its (case insensitive) value is @('"WRITE"')
 provided @(':useless-runes nil') is not supplied explicitly.  This feature
 supports the use of the environment variable when using @('make') to update
 @useless-runes.lsp files for the community books.</p>

 <p>If you want certification to avoid reading the book's @useless-runes.lsp
 file even when this environment variable has a non-empty value that specifies
 reading, use option @(':useless-runes nil').</p>

 <p>A reason for allowing integer values, rather than only @(':read') and
 @(':read?'), is that the disabling of useless runes can cause a proof to fail.
 Although this is probably uncommon, it can happen, for example because an
 otherwise useless rule rewrites the hypothesis of rule R to something that can
 not be proved by rewriting, thus blocking the use of rule R; but with the
 useless rule disabled, R is successfully applied, sending the proof in a
 direction that leads to failure.  This problem may disappear when using only a
 portion of the useless rules.  See also @(see
 accumulated-persistence-subtleties).</p>

 <p>Note that when using the @useless-runes.lsp file for a given event's
 proofs, then the appropriate rules are effectively @(see disable)d not only at
 the top level, but also whenever @(see hints) are supplied.  So if an
 @(':')@(tsee in-theory) hint specifies a @(see theory) that includes rule R,
 but rule R is specified for disabling for the current event by the
 @useless-runes.lsp file, then R will be removed from the theory before
 installing that hint.  In particular, even the hint @(':in-theory (enable
 ')R@(')') will not enable R in this case.</p>

 <p>Finally, we remark that the @useless-runes.lsp file is somewhat robust in
 the following sense.  Suppose that rule R is specified in that file, but at
 the time the @useless-runes.lsp is read, rule R has been removed from one's
 books.  Then the inclusion of R as a useless rule will simply be ignored,
 rather than causing an error.</p>

 <h3>Subtleties</h3>

 <p>The @useless-runes.lsp files do not contain any @(':')@(tsee
 executable-counterpart) runes, because there are many places that ACL2 does
 not track such runes for @(tsee accumulated-persistence).
 (Details are in a comment in the ACL2 source definition of function
 @('print-useless-runes').)</p>

 <p>On rare occasions, when using the @(':read') option or related values that
 specify reading from an appropriate @useless-runes.lsp file, the @(see
 package) of a rune's name might not be known to ACL2 at read time.  In that
 case, that rune will be ignored.</p>

 <p>Because of @(see local) @(see events), more than one event may be
 associated with a name in a given @useless-runes.lsp file.  When using the
 @(':read') option or related values that specify reading from an appropriate
 @useless-runes.lsp file, ACL2 considers entries for a given name from top to
 bottom in the @useless-runes.lsp file, attempting to match them to @(tsee
 defthm), @(tsee defun), and @(tsee verify-guards) events from top to bottom in
 the book.</p>

 <p>As suggested by discussions above, a @useless-runes.lsp file is intended
 not to cause proof failures, even if it is older than the corresponding book
 or even older than other books containing runes that are listed in that
 @useless-runes.lsp file.  That said, an out-of-date @useless-runes.lsp might
 cause proofs to fail.  In particular, imagine that there are several lemmas in
 the corresponding book all with the same name (and thus all @(see local) to an
 @(tsee encapsulate) event except perhaps the last), and one of those lemmas
 other than the last is deleted from the book.  Then references to the later
 such lemmas will be wrong in the @useless-runes.lsp file.  If you run into
 this problem, then either regenerate the @useless-runes.lsp file (e.g., using
 @('certify-book') with environment variable @('ACL2_USELESS_RUNES') set to
 @('"write"')), or give distinct names to your book's lemmas, or even
 consider adding a line like the following to a suitable @('.acl2') file (see
 @(see build::custom-certify-book-commands)).</p>

 @({
 ; cert-flags: ? t :useless-runes nil
 })

 <h3>Adaptations for @(tsee ld)</h3>

 <p>The @(':useless-runes') keyword argument was originally developed for
 @(tsee certify-book), and that is probably still where it is most useful.  But
 when developing or updating a book @('"BK"'), it may be convenient to
 evaluate the book's @(see events) using @('(ld "BK.lisp" .. :useless-runes
 ..)').  In that case, it is probably a good idea to run that @('ld') command
 in the same certification @(see world) (i.e., the world with the same sequence
 of @(see portcullis) commands) as will be encountered when certifying the
 book, so that the accesses to the @useless-runes.lsp will match up between the
 @('ld') call and a corresponding @('certify-book') call.  The following
 observations may help in that respect.</p>

 <ul>

 <li>If @('"BK.lisp"') has previously been certified, there should be a file
 @('"BK.port"').  By executing @('(ld "BK.port")'), you will put yourself
 in the appropriate certification world (unless the book's @(see portcullis)
 commands have changed since the time it was certified).</li>

 <li>If your @('ld') of the book ends prematurely in an error, then before you
 call @('ld') again with a @(':useless-runes') argument, it would very likely
 be best to back up (using @(':')@(tsee ubt)) so that you are once again in the
 intended certification world.</li>

 </ul>

 <p>Here are a few differences between @('ld') and @('certify-book') with
 respect to useless-runes.  For purposes of this discussion, let's say a call
 of @('ld') is ``a book-like call'' if the first argument is a string ending
 with @('".lisp"').</p>

 <ul>

 <li>Just as how @('certify-book') consults environment variable
 @('ACL2_USELESS_RUNES') for an implicit value of omitted keyword argument
 @(':useless-runes'), a book-like call of @('ld') consults environment variable
 @('ACL2_USELESS_RUNES_LD').  For example, if environment variable
 @('ACL2_USELESS_RUNES_LD') has value @('"50"'), then the call @('(ld
 "foo.lisp")') will be treated as though it were the call @('(ld
 "foo.lisp" :useless-runes 50)').</li>

 <li>If environment variable @('ACL2_USELESS_RUNES_LD') takes on the special
 value @('"cert"'), case-insensitive, then @('ld') will consult environment
 variable @('ACL2_USELESS_RUNES') just as @('certify-book') does.</li>

 <li>It is an error for a call of @('ld') that is not book-like to have a
 non-@('nil') @(':useless-runes') argument.  For a call of @('ld') without a
 @(':useless-runes') argument, environment variables supply a useless-runes
 value (as described above) only if it is a book-like call.</li>

 <li>The value of keyword argument @(':useless-runes') in a call of
 @('certify-book') or @('ld') does not persist to a subsidiary call of
 @('certify-book') or @('ld').  If you want a useless-runes value to persist,
 use environment variables.</li>

 <li>Recall that for @('certify-book'), the environment variable takes priority
 if its (case insensitive) value is @('"write"') provided the
 @(':useless-runes nil') keyword argument is not supplied.  But for @('ld'), an
 explicit value of the @(':useless-runes') keyword argument always takes
 priority; environment variables, even with value @('"write"'), do not
 override any such value.</li>

 </ul>

 <h3>Performance</h3>

 <p>In ``everything'' testing of all of the @(see community-books) during
 (not quite complete) development of this capability, we found that writing the
 @useless-runes.lsp files (by setting the environment variable
 @('ACL2_USELESS_RUNES') to @('"write"')) caused an 11% slowdown from the
 normal time, but a fresh such test when reading the @useless-runes.lsp files
 by setting the environment variable @('ACL2_USELESS_RUNES') to @('"25"') cut
 24% from the normal time.  Books varied considerably, however.  For example,
 after finding a specific time reduction that was particularly significant, we
 re-certified on standalone runs (i.e., on an otherwise unloaded machine) and
 found that the time was reduced from 17 minutes and 1.9 seconds down to 34.93
 seconds, thus eliminating 96.6% of the time.</p>")
other
(defxdoc useless-runes-failures
  :parents (failure useless-runes)
  :short "Failures caused by @(see useless-runes)"
  :long "<p>When an event fails you may see the following message:</p>

 @({
 *NOTE*: Useless-runes were in use and can affect proof attempts.  See
 :DOC useless-runes-failures.
 })

 <p>This message may be printed after the usual failure message when a @(see
 useless-runes) file has been consulted during proofs, as is usually the case
 when using build system tools (see @(see books-certification) and @(see
 build::cert.pl)).  It is intended to suggest that you consider removing or
 regenerating the associated @(see useless-runes) file in the situation
 described below.</p>

 <p>Suppose that you have developed a book &mdash; say, @('foo.lisp') &mdash;
 and placed it into the @(see community-books).  Then @(see regression) runs
 may occasionally generate (or regenerate) the associated @(see useless-runes)
 file.  Now suppose you modify @('foo.lisp') or some books that are included in
 it.  You successfully run @('(certify-book "foo")'); yet, certification of
 @('foo.lisp') subsequently fails as part of a @(see regression) run or when you
 use @(tsee build::cert.pl) to certify @('foo.lisp').  This could be
 unsettling!</p>

 <p>In that case, what is probably happening is that the @(see useless-runes)
 file is no longer suitable.  If you are a contributor to the ``ACL2 System and
 Community Books'' GitHub project (see @(see git-quick-start)), you can update
 repository as follows (followed by the usual actions when updating the
 repository).</p>

 @({
 git rm .sys/foo@useless-runes.lsp
 })

 <p>Or, if you like, you could regenerate the useless-runes file, for example
 as follows.</p>

 @({
 (certify-book "foo" ? t :useless-runes :write)
 })


 <p>Or if you prefer to avoid this useless-runes file from now on, you could
 add a line like the following to @('foo.acl2') (see @(see
 build::custom-certify-book-commands)) and also, ideally, delete the
 useless-runes file using the @('"git rm"') command displayed above.</p>

 @({
 ; cert-flags: ? t :useless-runes nil
 })")
other
(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>")
other
(defxdoc user-stobjs-modified-warnings
  :parents (trans-eval stobj)
  :short "Interactions of @(tsee trans-eval) with @(see stobj)s that violate
 applicative semantics"
  :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 certain @(see warnings) that may be issued by @('trans-eval') for
 @(see stobj) updates that may violate applicative semantics.  Also see @(see
 trans-eval-and-locally-bound-stobjs) for how @('trans-eval') relates to
 updates of locally bound stobjs.</p>

 <p>Please see @(see trans-eval) and @(see trans-eval-and-stobjs) for relevant
 background.</p>

 <p>Consider the following log.</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) may have modified the user stobj ST.  See
 :DOC user-stobjs-modified-warnings.

 (4 <state> <st>)
 ACL2 !>
 })

 <p>The warning is intended to indicate that a @(see stobj) may have been
 modified even though that stobj was accessed indirectly, through the ACL2
 @(see state).  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>Below we discuss the following events, which were evaluated before
 producing the log above.</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 near the top of this topic.  That log is
 actually very surprising if you think about it, since the @('trans-eval') call
 in the definition of @('foo') modifies only the @('state') parameter, not the
 @('st') parameter, and yet the value @('st') has changed: @('(fld st)') has
 changed from 3 to 4, while evaluating code in which @('st') does not occur
 free!  Let us discuss this point further.</p>

 <p>First 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!  So the first return value of 4, above, can very
 reasonably be considered to violate applicative semantics.  ACL2 acknowledges
 this concern &mdash; that is, the concern that an operation (i.e., @('fld'))
 now gives a different result on an object (i.e., @('st')) that ``should'' not
 have changed, thus violating normal applicative semantics &mdash; by printing
 the warning displayed above.</p>

 <p>To see how this can happen, consider that in raw Lisp the stobj, @('st'),
 is actually a one-element array whose unique value is @('(fld st)').  The
 @('trans-eval') call in @('foo') replaces that element, in this case 3, with a
 new value, in this case 4.  It does this <i>destructively</i>: the memory
 location of @('st') is not changed.  Thus, evaluation of @('(fld st)') after
 the @('trans-eval') call now returns the new array element, which is 4.</p>

 <p>Worse yet, there are similar cases where there is <i>no</i> such violation
 of applicative semantics!  We return to this point later below.  First we
 provide some additional discussion of such warnings, as well as observations
 for tool writers who want to eliminate the warnings.</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
 applicative semantics.  The warning is, at least, an acknowledgment of this
 situation.</p>

 <p>We next discuss how to write tools that avoid producing such warnings, and
 the advisability (or not) of doing so.</p>

 <p>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, perhaps because you are convinced that no
 stobj parameter is modified indirectly using @('trans-eval').  Think carefully
 about whether you really don't want them to see the warning!  After all, they
 may be relying on normal applicative 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 violations of applicative semantics are reported.
 These warnings are unimportant for the top-level calls of @('trans-eval') that
 implement the ACL2 read-eval-print 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>

 <p>We now elaborate on a point made briefly above, that there are cases where
 the usual violation of applicative semantics does not take place.  This
 happens when the underlying raw Lisp stobj is actually replaced, which happens
 when there is a single stobj field that is either an array being resized or a
 hash table being initialized (with the ``clear'' or ``init'' function); see
 @(see defstobj).  Consider the following example.</p>

 @({
 (defstobj st2 (ar :type (array t (10)) :resizable t))

 (defun foo2 (st2 state)
   (declare (xargs :stobjs (st2 state)
                   :mode :program))
   (let ((st2 (update-ari 3 'old st2)))
     (mv-let (erp val state)
       (trans-eval '(let ((st2 (resize-ar 20 st2)))
                      (update-ari 3 'new st2))
                   'foo state nil)
       (declare (ignore erp val))
       (mv (ari 3 st2) state st2))))
 })

 <p>After submitting these forms, evaluation of the form @('(foo2 st2 state)')
 produces @('(OLD <state> <st2>)').  But based on the first example, @('foo'),
 we might expect that destructive modification of @('st2') would result instead
 in @('(NEW <state> <st2>)').  Indeed, if the first argument of @('trans-eval')
 in the definition of @('foo2') is instead @('(update-ari 3 'new st2))'), then
 the result is @('(NEW <state> <st2>)').  So why do we get the OLD result using
 the definition of @('foo2') displayed above?</p>

 <p>The reason is that when a stobj has a single field, and that field is an
 array or hash table, then in raw Lisp the stobj <i>is</i> exactly that field.
 When we call @('resize-ar'), the entire array is rebuilt, and thus the stobj
 is at a new memory location.  To be precise: After the resizing, then the
 value of @('st2') in the @('user-stobj-alist') of the ACL2 state is a new
 stobj: the actual parameter @('st2') of @('foo2') is not destructively
 modified.  Thus, normal applicative semantics apply: the final value of
 @('(fld st2)') is independent of the replacement of @('st2') in the
 @('user-stobj-alist') hence is still 3 (from the first update).</p>

 <p>We close with a more realistic example.
 (It is based on our experience modifying the definition of the macro,
 @('local-test'), in @(see community-book)
 @('books/system/tests/nested-stobj-tests.lisp'), when we changed ACL2 so that
 the stobj is the entire array field when there is only that one field.)  The
 @(tsee make-event) call below fails, because the resizing operation replaces
 the stobj in the global @('user-stobj-alist') of the ACL2 @(see state), but
 the call of @('EQUAL') still references the original stobj.  This failure is
 thus exactly as expected for an applicative semantics.  However, it fails only
 because the resize operation is not destructive: it replaces the entire
 stobj.</p>

 @({
 (defstobj st3 (ar3 :type (array t (10)) :resizable t))

 ; Fails (see discussion above):
 (make-event
  (er-progn (trans-eval '(let ((st3 (resize-ar3 30 st3)))
                           (update-ar3i 24 'done st3))
                        'top
                        state t)
            (value (equal (ar3i 24 st3) 'done))
            (value '(value-triple :success))))

 ; Passes because by now, the user-stobj-alist has been updated by
 ; the top-level call of trans-eval to implement the ACL2
 ; read-eval-print loop:
 (assert-event (equal (ar3i 24 st3) 'done))

 ; The following version passes because the second trans-eval call
 ; below references the value of st3 in the user-stobj-alist that was
 ; produced by the first trans-eval call below.
 (make-event
  (er-progn (trans-eval '(let ((st3 (resize-ar3 40 st3)))
                           (update-ar3i 34 'new st3))
                        'top state t)
            (trans-eval '(if (equal (ar3i 34 st3) 'new)
                             (value nil)
                           (er soft 'top "Failed!"))
                        'top state t)
            (value '(value-triple :success))))
 })")
other
(defxdoc using-acl2
  :parents (installation about-acl2)
  :short "Using ACL2"
  :long "<p><b>Table of Contents</b></p>

 <ul>
 <li>Invoking ACL2</li>
 <li>Testing ACL2</li>
 <li>Certifying ACL2 Books</li>
 <li>Documentation</li>
 <li>Emacs</li>
 </ul>

 <h3>Invoking ACL2</h3>

 <p>We assume that you have followed the @(see installation) instructions to
 install ACL2.  The sources and, in general, an executable image are located in that
 directory.  However, if you have not saved an executable image but instead use the
 directions for running ACL2 without building an executable image
 (see @(see running-acl2-without-executable)), skip to &ldquo;When ACL2 Starts
 Up&rdquo; below.</p>

 <p>Invoke ACL2 by running the executable file, @('saved_acl2'), for example as
 follows (but you can supply a suitable pathname if you are not standing in the
 directory that contains @('saved_acl2')).</p>

 @({
 mycomputer% ./saved_acl2
 })

 <p>If you on a Unix-like system, then to make it easy to invoke ACL2 by typing
 a short command, e.g.,</p>

 @({
 mycomputer% acl2
 })

 <p>you may want to install an executable file on your path, e.g.,
 @('~/bin/acl2'), containing the following two lines where @('<path>') is the
 absolute pathname for the directory of @('saved_acl2').</p>

 @({
 #!/bin/sh
 <path>/saved_acl2 "$@"
 })

 <p>Note: A carriage return in the file after the last line above may be
 important!</p>

 <p><i>When ACL2 Starts Up</i></p>

 <p>When you invoke ACL2, you should see the host Common Lisp
 print a header concerning the ACL2 version, license and copyright.</p>

 <p>Most or all hosts then automatically enter the ACL2 <i>command loop</i>, an
 ACL2 read-eval-print loop with the prompt:</p>

 @({
 ACL2 !>
 })

 <p>In the very unlikely case that a host leaves you in Common Lisp's
 read-eval-print loop, then you'll need to evaluate the Common Lisp expression
 @('(ACL2::LP)') or simply @('(LP)') if the current package is
 @('"ACL2"').</p>

 <p>Once in the ACL2 command loop, you can type an ACL2 term, typically
 followed by ``return'' or ``enter,'' and ACL2 will evaluate the term,
 print its value, and prompt you for another one.  Below are three
 simple interactions.</p>

 @({
 ACL2 !>t
 T
 ACL2 !>'abc
 ABC
 ACL2 !>(+ 2 2)
 4
 })

 <p>To get out of the ACL2 command loop, type the @(':q') command.  This
 returns you to the host Common Lisp.  We sometimes call this ``raw Lisp.''
 You may re-enter the command loop with @('(LP)') as above.  To quit ACL2 (and
 Lisp) entirely, submit the command, @('(quit)').</p>

 <p>Note that when you are in raw Lisp you can overwrite or destroy ACL2 by
 executing inappropriate Common Lisp expressions.  <b>All bets are off once
 you've exited the ACL2 loop.</b> That said, this is typically safe and many
 users do it.  For example, you might exit the ACL2 loop, activate some
 debugging or trace features in raw Lisp, and then reenter the ACL2 loop.
 While developing proofs or tracking down problems, this can occasionally be
 reasonable behavior.</p>

 <p>Now you are ready to test your copy of ACL2.</p>

 <h3>Testing ACL2</h3>

 <p>An easy way to test the theorem prover is to
 type the following term to the ACL2 command loop.</p>

 @({
 :mini-proveall
 })

 <p>This will cause a sequence of commands to be processed, each of which is
 first printed out as though you had typed it.  Each will print some text,
 generally a proof of some conjecture.  None should fail.</p>

 <p>A more elaborate test is to certify the community books; see @(see
 community-books) and @(see certify-book).  This certification is a good idea
 anyhow; this is our next topic.  On a Unix-like system, you can also certify
 just a small but useful subset of the books in a few minutes by executing
 @('make basic') in either the main ACL2 directory or the @('books/')
 subdirectory.</p>

 <h3>Certifying ACL2 Books</h3>

 <p>The <see topic='@(url community-books)'><i>community books</i></see>, which
 reside in subdirectory @('books/'), have been contributed by many ACL2 users.
 See @(see books) for a through discussion of the general topic of books.</p>

 <p>Books should be <i>certified</i> before they are used.  ACL2 is distributed
 without book @(see certificate)s, mainly because certification produces
 compiled code specific to the host.  You should certify the books locally,
 both as a test of your ACL2 image and because books generally need to be
 certified before they can be used.  See @(see installation), or more
 specifically @(see installation-instructions), for how to perform this
 certification.  For additional explanation and further options, see @(see
 books-certification).</p>

 <h3>Documentation</h3>

 <p>See @(see documentation) for a discussion of ACL2's documentation system.
 To query ACL2 about a built-in topic, @('<topic>'), submit @(':DOC <topic>')
 to ACL2.</p>

 <h3>Emacs</h3>

 <p>Emacs users may find it helpful to load into emacs the file
 @('emacs/emacs-acl2.el') for Emacs 24 or 25 or the file
 @('books/emacs/emacs-acl2.el') for later Emacs versions.  Utilities offered by
 this file are documented near the top of the file.  In particular, this file
 automatically loads the @(see acl2-doc) Emacs-based browser for ACL2
 documentation.</p>")
other
(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>")
other
(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))
 })")
other
(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 @(see
 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>")
other
(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 @(see 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>")
other
(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 @(see 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>")
other
(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>")
other
(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 @(see
 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 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 a 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>")
other
(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 has 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 @(see 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 will print an
 ``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)))
 })")
other
(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 @(see
 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>")
other
(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 the formula
  of an enabled :REWRITE or :DEFINITION rule, so you may want to consider
  disabling (:REWRITE CDR-CONS) in the hint provided for Subgoal *1/1.
  See :DOC using-enabled-rules.
 })

 <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>")
other
(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>")
other
(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>")
other
(defxdoc value-triple
  :parents (events acl2-built-ins errors)
  :short "Compute a value, optionally checking that it is not @('nil')"
  :long "<h3>Simple Example</h3>

 @({
 ; Return the value 7 as an error triple, i.e., (mv nil 7 state)).
 (value-triple (+ 3 4))
 })

 <h3>Examples Involving Keyword Arguments</h3>

 @({
 ; Print "hi" even when skipping proofs.
 (value-triple (cw "hi") :on-skip-proofs t)

 ; Return an error triple containing the value of a state global.
 ; (This shows that it's OK to reference state.)
 (value-triple (@ ld-pre-eval-print))

 ; Check that the given form returns a non-nil value.
 (value-triple (equal (+ 3 4) 7) :check t)

 ; Check that the given defun is admissible, then revert the world.
 (value-triple (er-progn (defun foo (x) (cons x x))
                         (value :success))
               :stobjs-out :auto)
 })

 <h3>General Form</h3>

 @({
 (value-triple form
               :check chk             ; default nil
               :ctx                   ; default 'value-triple
               :on-skip-proofs sp     ; default nil
               :safe-mode safe-mode   ; default :same
               :stobjs-out stobjs-out ; default nil
               )
 })

 <p>where all keyword arguments are evaluated and optional, and the defaults
 shown above represent values after evaluation.</p>

 <p>The following example illustrates all of the keyword arguments, which are
 documented below.</p>

 @({
 (value-triple (mv nil (equal (+ 3 4) 7) state)
               :check (msg "Oops, I forgot what ~x0+~x1 is!" 3 4)
               :ctx '(value-triple . <some-mv>)
               :on-skip-proofs t
               :safe-mode nil ; legacy behavior (rarely used)
               :stobjs-out '(nil nil state))
 })

 <h3>Description</h3>

 <p>@('Value-triple') provides a convenient way to evaluate a form in a context
 where an @(see event) is expected; thus, a call of @('value-triple') may occur
 in @(tsee progn) and @(tsee encapsulate) forms and in @(see books).  By
 default, the form should evaluate to a single, non-@(see stobj) value (but see
 the discussion below about the @(':STOBJS-OUT') keyword argument).  Calls of
 @('value-triple') are skipped by default when proofs are being skipped (but
 see the discussion below about the @(':ON-SKIP-PROOFS') keyword argument).  By
 default, a @('value-triple') call has no effect other than to evaluate its
 form, but see the discussion of the @(':CHECK') keyword below for how to check
 the result.</p>

 <p>A call of @('value-triple') returns an @(see error-triple), @('(mv erp val
 state)').  By default or when @(':CHECK nil') is supplied: @('erp') is
 @('nil') when evaluation completes without error and @('val') is the value
 returned by evaluating the given form.  However, when the keyword argument
 @(':CHECK') has a non-@('nil') value, there is a check that @('val') is
 non-@('nil').  Note that the value of keyword argument @(':STOBJS-OUT') can
 affect this notion of ``the value returned'' (by evaluation), as discussed
 below.</p>

 <h3>Keyword Arguments</h3>

 <p>Here is documentation for the keyword arguments, arranged alphabetically
 and followed by relevant remarks.</p>

 <p>@(':CHECK chk') (default: @('nil'))</p>

 <p>When @('chk') is supplied and non-@('nil'), the value returned by
 evaluating the given form must be non-@('nil'), or else an error occurs: The
 error message is generic if @('chk') is @('t').  (By default a single value is
 returned, so the notion of ``the value returned'' is clear; but see the
 discussion of @(':STOBJS-OUT') below for the notion of ``the value returned''
 in the general case.)  If @('chk') is supplied and is neither @('t') nor
 @('nil'), then it should be a ``message'' (see @(see msg)) that is used when
 printing the error message.</p>

 <p>@(':CTX ctx') (default: @(''value-triple'))</p>

 <p>Error messages from @('value-triple') start, by default, with ``ACL2 Error
 in VALUE-TRIPLE''.  To replace @('VALUE-TRIPLE') with a different context (see
 @(see ctx)), @('ctx'), supply keyword argument @(':CTX ctx').</p>

 <p>@(':ON-SKIP-PROOFS sp') (default: @('nil'))</p>

 <p>By default or when @(':ON-SKIP-PROOFS') has value @('nil'), the form is not
 evaluated when proofs are being skipped.  The form is, however, evaluated when
 @(':ON-SKIP-PROOFS t') is supplied.  The other legal value for
 @(':ON-SKIP-PROOFS') is @(':interactive'), which is more restrictive than
 @('t').  @(':Interactive') directs the @('value-triple') call to be skipped
 when executing an @(tsee include-book) or making a second pass through an
 @(tsee encapsulate), but not merely because @('(set-ld-skip-proofsp t state)')
 has been executed.</p>

 <p>@(':SAFE-MODE safe-mode') (default: @(':same'))</p>

 <p>It is usually safe to ignore this option, which is available for backward
 compatibility: @(':SAFE-MODE t') gives the behavior of @('assert-event') from
 before April, 2021.  Normally ACL2 operates without so-called ``safe-mode'';
 see @(see safe-mode).  The value @(':same') prevents any change in whether
 safe-mode is on or off; otherwise the value is @('t') to evaluate the form
 with safe-mode on and @('nil') for safe-mode off.</p>

 <p>@(':STOBJS-OUT stobjs-out') (default: @('nil'))</p>

 <p>When @('stobjs-out') has its default value of @('nil'), which abbreviates
 the value @('(nil)'), the form supplied to @('value-triple') is expected to
 evaluate to a single value that is neither a @(see stobj) nor a @(see df).
 However, @(see multiple-value) return is also allowed, including
 stobjs (user-defined stobjs as well as @('state')).  The return shape is
 specified by supplying @('stobjs-out') as a true list corresponding to the
 values returned, with stobj names in stobj positions and, @(':DF') in df
 positions, and @('nil') elsewhere.  (The list has length one if a single value
 is returned.)  For example, if @('stobjs-out') is @('(nil st1 nil st2)') then
 the form should evaluate to a @(see multiple-value) return, with ordinary
 values in (zero-based) positions 0 and 2, stobj @('st1') in position 1, and
 stobj @('st2') in position 3.</p>

 <p>@('Stobjs-out') may also be @(':auto'), which allows arbitrary returns.</p>

 <p>We speak of ``the value returned''.  When the evaluation results in a
 single value, that is of course the value returned.  When multiple values are
 returned, the first of those values is normally what we mean by ``the value
 returned'', with the following exception.  When an @(see error-triple) is
 returned &mdash; say @('(mv erp val state)') where @('erp') is an ordinary
 value, @('val') is a non-@(see stobj) value, and @('state') is the ACL2 @(see
 state) &mdash; then @('val') is considered to be the value returned if
 @('erp') is @('nil'); but if @('erp') is not @('nil'), then there is no value
 returned, and @('value-triple') results in an error.</p>

 <p>If @(':CHECK') has a non-@('nil') value then the value returned must not be
 a stobj.  Otherwise, when the value returned is a stobj it is replaced by the
 stobj's name, as discussed below.</p>

 <h3>Remarks</h3>

 <p>We conclude by remarking on some details.  These remarks also apply to
 @(see assert-event), since it expands to make corresponding calls of
 @('value-triple').</p>

 <ol>

 <li>Since @('value-triple') is an @(see event) macro, it returns an @(see
 error-triple), that is, the multiple values @('(mv erp val state)'), where
 @('erp') is @('nil') exactly when the event completes without error.  If the
 value of keyword argument @(':CHECK') is non-@('nil') and @('erp') is
 @('nil'), then @('val') is @(':passed').  Otherwise @('val') is the value
 returned as discussed above.  To be precise: @('val') is the result of
 evaluating the given form in the default case, when @(':STOBJS-OUT') is not
 provided (or is @('nil') or @('(nil)')), but in general there several cases
 possible, as follows.</li>

 <ul>

 <li>If the evaluation of the given form results in a single ordinary value,
 then @('val') is that value.</li>

 <li>If the evaluation of the given form results in a single stobj value, then
 @('val') is that stobj's name (a symbol).  In particular, if the value is
 state, then @('val') is the symbol @('STATE') (in the @('"ACL2"')
 package).</li>

 <li>If the evaluation of the given form results in a single @(see df) value,
 then @('val') is the corresponding rational number.</li>

 <li>If the evaluation of the given form results in multiple values @('(mv x1
 ...)'), then @('val') is @('x1') if @('x1') is not a stobj (but converted to a
 rational if @('x1') is a @(see df)), else @('val') is the name of that
 stobj.</li>

 </ul>

 <li>When @(':STOBJS-OUT') is @(':auto') and at least one user-defined @(see
 stobj) is returned, you will see a @('"User-stobjs-modified"') warning
 unless warnings have been suppressed.  Although warnings are typically
 suppressed by general utilities such as @(tsee set-inhibit-output-lst), @(tsee
 set-inhibit-warnings), and @(tsee with-output), a more direct way to avoid
 this warning is to specify @(':STOBJS-OUT') as a list (as discussed
 above).</li>

 <li>As noted above, the ACL2 @(see state) may change when keyword option
 @(':STOBJS-OUT') has a value other than @('nil') or @('(nil)').  Nevertheless,
 ACL2 ensures that certain parts of the state, including the logical @(see
 world), are the same after the @('value-triple') call completes as they were
 before (as with @('make-event') expansion; see @(see make-event)).  Also,
 trust tags (see @(see defttag)) must not be introduced during such
 evaluation.</li>

 <li>(Ignore this remark unless you make many, many calls of
 @('value-triple').)  Evaluation may be much faster when @(':STOBJS-OUT') is
 omitted or is specified as @('nil') (the default) or @('(nil)').  That is
 because otherwise, since the return shape is checked only after evaluation
 completes, therefore a somewhat complex environment set-up is performed prior
 to evaluation, in which certain parts of the ACL2 @(see state) are protected
 as for @(tsee make-event) (using @(tsee revert-world), and also as discussed
 in the documentation for @(tsee make-event) about
 @('*protected-system-state-globals*')).  Moreover, evaluation is faster still
 if in addition, the given form is @('t'), @('nil'), a @(see keyword), or of
 the form @('(QUOTE x)').</li>

 </ol>")
other
(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>")
other
(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>")
other
(defxdoc verify-guard-implication
  :parents (memoize guard-formula-utilities)
  :short "@(csee Guard) implication for @(tsee memoize) keyword @(':invoke')"
  :long "@({
 Examples:
 (verify-guard-implication f g)
 (verify-guard-implication f g
                           :hints (("Goal" :in-theory (enable nth))))

 General Form:
 (verify-guard-implication fn1 fn2 &key hints otf-flg)
 })

 <p>where none of the arguments is evaluated.  This macro creates a @(tsee
 defthm) event with @(':')@(tsee rule-classes) @('nil'), using @(':hints') and
 @(':otf-flg') if provided.  The formula of that event is generally an
 implication formed from the guards of the two functions, but might be @('T'),
 as we now describe.</p>

 <p>Let @('guard-fn1') be the @(see guard) for @('fn1'), and let @('guard-fn2')
 be the result of substituting the formals of @('fn1') for the formals of
 @('fn2') in the guard for @('fn2').  If @('guard-fn1') tautologically implies
 @('guard-fn2') (for example, the two are equal or @('guard-fn2') is @(''T')),
 then the formula of the generated event is @('T').  Otherwise, the formula is
 @('(IMPLIES guard-fn1 guard-fn2)').</p>

 <p>Note that the formula might be unpleasant for a human to read, since
 @('guard-fn1') and @('guard-fn2') are translated terms (see @(see
 term)).</p>")
other
(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') @(see event), we first discuss
 @(see 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 Notes: (1) The first argument of @('verify-guards') must be a
 function symbol, the name of a @(tsee defthm) or @(tsee defaxiom) event, a
 @(tsee lambda$) expression, or an unquoted well-formed @('LAMBDA') object; it
 must not be 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.  (2) When the guards of a defined function, @('fn'),
 are verified, @('verify-guards') also includes the guards of all the functions
 that are mutually recursive with @('fn'), if any, plus the guards of all the
 quoted well-formed @('LAMBDA') objects used by @('fn') or any function in its
 mutually-recursive clique.  Guard obligations for @('lambda$') and @('LAMBDA')
 objects are <i>not</i> included when the first argument is the name of a
 theorem or axiom.  Details are discussed further below.</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.  (However, additional conjectures are
 generated for @('loop$') statements.  See the section <b>Special Guard
 Conjectures for LOOP$</b> in the documentation for @(tsee loop$).)</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
                 :guard-simplify :limited ; default = t
                 :otf-flg t)
  (verify-guards (lambda$ (x)
                   (declare (xargs :guard (natp x)))
                   (+ 1 x)))
  (verify-guards
    (LAMBDA (X)
            (DECLARE (XARGS :GUARD (NATP X) :SPLIT-TYPES T))
            (RETURN-LAST 'PROGN
                         '(LAMBDA$ (X)
                                   (DECLARE (XARGS :GUARD (NATP X)))
                                   (+ 1 X))
                         (BINARY-+ '1 X))))

  General Form:
  (verify-guards name
          :hints          hints
          :guard-debug    gdbg ; default generally nil; any value is legal
          :guard-simplify gsmp ; default generally t; may be set to :limited
          :otf-flg        otf-flg)
 })

 <p>In the General Form above, @('name') may be the name of a @(':')@(tsee
 logic) mode function (see @(see defun-mode)).  In that case, the first three
 keywords may default to values in an existing definition as discussed below.
 Otherwise, @('name') is the name of a theorem or axiom, or it is a @(tsee
 lambda$) expression or a well-formed @('LAMBDA') object (not <i>quoted</i>).
 @(see Mixed-mode-functions) cannot be guard verified.</p>

 <p>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, but @('hints') and @('guard-debug') can be taken from the existing
 definition of @('name'); we return to that point later.  The keyword arguments
 above are all optional.  To admit this event, the conjunction of the guard
 proof obligations must be proved.  If all the guard obligations are proved,
 @('name') is considered to have had its @(see guard)s verified.  The
 @(':guard-simplify') option controls certain simplifications that may be
 applied to the guard conjecture while generating the initial goal: its default
 is @('t'), which doesn't restrict such simplification, and the other legal
 value is @(':limited'), which skips all simplifications that depend on the set
 of currently @(see enable)d rules; but as with @('hints') and
 @('guard-debug'), the value can be taken from the existing definition of
 @('name'), as described further below.  See also @(see
 guard-simplification).</p>

 <p>If @('name') is a @('lambda$') expression it is translated (to a quoted
 well-formed @('LAMBDA') object), the formals, declaration, and body are
 extracted, and @('verify-guards') behaves as though @('name') were the name of
 some defined function with those formals, declaration, and body.  If @('name')
 is a @('LAMBDA') object, it is checked for well-formedness (see @(tsee
 well-formed-lambda-objectp)), the formals, declaration, and body are extracted
 @('verify-guards') behaves as though @('name') were the name of some defined
 function with those formals, declaration, and body.  for @('lambda$').  We
 henceforth limit our attention to @('name') being the name of a function,
 theorem or axiom.</p>

 <p>Note: Since we encourage you to use @('lambda$') instead of trying to type
 quoted well-formed @('LAMBDA') objects, you might wonder why we allow
 @('verify-guards') to operate on well-formed @('LAMBDA') objects instead of
 @('lambda$') expressions.  The answer is that in proof output and in @(tsee
 print-cl-cache) output you see quoted well-formed @('LAMBDA') objects and we
 expect you might grab the text of such an object and submit it to
 @('verify-guards').</p>

 <p>See @(see guard-formula-utilities) for related utilities, including ones
 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>As promised above, we now describe the case that @('name') was defined
 function symbol whose definition supplies the value of @(':hints'),
 @(':guard-debug'), and/or @(':guard-simplify').  This happens when those
 keywords are not supplied with the @('verify-guards') event but the existing
 definition specifies @(':guard-hints'), @(':guard-debug'), and/or
 @(':guard-simplify'), respectively, in its @(tsee xargs) @(see declaration).
 Note that when @('name') is defined as part of a @(tsee mutual-recursion)
 event, only declarations in the definition of @('name') are relevant, but
 those in definitions of other functions in the clique.  Consider the following
 example.</p>

 @({
 (defun my-consp (x)
   (declare (xargs :guard t))
   (consp x))

 (defun my-cdr (x)
   (declare (xargs :guard (my-consp x)))
   (cdr x))

 (mutual-recursion
  (defun evenlp (x)
    (declare (xargs :verify-guards nil))
    (if (consp x) (oddlp (my-cdr x)) t))
  (defun oddlp (x)
    (declare (xargs :guard-hints
                    (("Goal" :in-theory (disable my-consp (tau-system))))))
    (if (consp x) (evenlp (my-cdr x)) nil)))
 })

 <p>Each of the following succeeds or fails for the reason given.</p>

 @({
 ; Succeeds: :guard-hints for oddlp are ignored.
 (verify-guards evenlp)

 ; Fails: :guard-hints for oddlp defeat the proof attempt.
 (verify-guards oddlp)

 ; Succeeds: guard-hints for oddlp are ignored because :hints was supplied
 ; explicitly (even though :hints is nil, which is the default).
 (verify-guards oddlp :hints nil)
 })

 <p>If the guard or body of @('name') include any quoted well-formed
 @('LAMBDA') objects, @('verify-guards') include their proof obligations in
 those generated for @('name').  Roughly speaking, the guard obligations for a
 well-formed @('LAMBDA') object are exactly those that would be generated for a
 separately defined non-recursive function with the formals, guard, and body of
 the @('LAMBDA') object.  We discuss this further in the ``Remarks on
 @('LAMBDA') objects in defined functions'' below.  As a non-logical
 side-effect of the successful verification of all the proof obligations, all
 well-formed @('LAMBDA') objects in the guard or body of @('name') (including
 @('name') itself if it is a @('lambda$') expression or @('LAMBDA') object) are
 added to the compiled lambda cache.  This will speed up the execution of
 @('name') in the evaluation theory when those well-formed @('LAMBDA') objects
 are @('apply$')d.  See @(tsee print-cl-cache).</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>Remarks on @('LAMBDA') objects in defined functions</b>.  The guard
 obligations of a function, @('name'), include the guard obligations of every
 quoted well-formed @('LAMBDA') object occurring in either the guard or body of
 @('name').  We point this out because quoted well-formed @('LAMBDA') objects
 are, after all, just quoted constants and no other quoted constant generates
 guard obligations!  Note also that we collect <i>all</i> quoted well-formed
 @('LAMBDA') objects, not just the translations of @(tsee lambda$) expressions
 and not just objects in slots of @(see ilk) @(':FN').  (We do not actually
 expect the user to write quoted well-formed @('LAMBDA') objects in
 non-@(':FN') slots -- it can't be done with @('lambda$') expressions -- but we
 collect them all anyway.  If such a quoted constant is not guard verifiable,
 you could always use so-called Bypass 1 of @(see
 gratuitous-lambda-object-restrictions) and avoid quoting it.)  We assume that
 when calls of @('name') are executed some of those @('LAMBDA') objects may
 reach @('apply$') and be applied.  Those applications will be faster if the
 guards for the @('LAMBDA')s are verified too.  The guard obligations of a
 quoted well-formed @('LAMBDA') object are just those obligations that would be
 generated by a defined function with the same formals, guard, and body as the
 @('LAMBDA') object.  Those obligations are unioned with the rest of the
 obligations generated for @('name') and all must be proved for
 @('(verify-guards name)') to be successful.  If the guards of some @('LAMBDA')
 object requires hints to prove, the hints may be supplied to
 @('verify-guards') as you would for any other failing guard obligation in
 @('name').  When successful, the @('LAMBDA') objects thus verified are added,
 behind the scenes, to the compiled lambda cache (see @(tsee print-cl-cache))
 to speed up @('apply$') in the evaluation theory.</p>

 <p>Since, in general, @('LAMBDA') objects can be passed around or re-used in
 different contexts, the guard obligations generated for a quoted well-formed
 @('LAMBDA') object occurring in @('name') are entirely independent of the
 guard on the @('name') itself.  This is best explained by example.</p>

 <p>In the @('defun') below, which contains a @('lambda$') expression in its
 body, we assume each function has the guard shown below:</p>

 <code>
 function        formals              guard
 f                 (x)                (fp x)
 g                 (x y)              (gp x y)
 the lambda$       (x)                (lp x)
 r                 (x)                (rp x)
 s                 (x)                (sp x)
 </code>

 <p>We also assume that the ilks of @('g') are @(':FN') and @('NIL').  Then the
 guard obligations generated for</p>

 @({
 (defun f (x)
  (declare (xargs :guard (fp x)))
  (g (lambda$ (x)
              (declare (xargs :guard (lp x)))
              (r x))
     (s x)))
 })

 <p>is</p>

 @({
 (and
  (implies (fp x) (sp x))        ; f can call s
  (implies (fp x)                ; f can call g
           (gp (lambda$ (x)
                        (declare (xargs :guard (hg x)))
                        (r x))
               (s x)))
  (implies (lp x) (rp x))        ; the lambda$ can call r
  )
  })

 <p>Note: The actual obligation will have been generated from the fully
 translated body of @('f') and the @('lambda$') expression will have been
 converted to a quoted well-formed @('LAMBDA') object.  But we will refer to it
 as a @('lambda$') here for clarity.</p>

 <p>In particular note that the last conjecture, establishing that the
 @('lambda$') can call @('r'), does not have @('f')'s guard as a hypothesis.
 The @('lambda$') is being guard verified in a ``context free'' way because we
 cannot (or at least do not) trace the hypotheses governing every time it is
 called in @('g') and the variable @('x') in @('f') and its guard is unrelated
 to the local variable @('x') in the @('lambda$').  Furthermore, if @('apply$')
 ever encounters this @('lambda$') it will know it has been guard
 verified (because it finds it marked as such in the cache) and it may well
 <i>not</i> be under a call of @('f').  Be that as it may, the guard
 obligations of the @('lambda$') are included in the guard obligations for
 @('f').  As of ACL2 Version 8.1, the guard obligation that @('g') can call the
 @('lambda$') is checked by computation every time the @('lambda$') is
 @('apply$')d.  That is, @('(lp x)') is run on each object the @('lambda$') is
 @('apply$')d to and the compiled code for the @('lambda$') is run only if its
 guard approves.</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>")
other
(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>")
other
(defxdoc verify-guards-for-system-functions
  :parents (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 guard-verified @(':logic') mode, you might
 first need or want to modify your local copy of the ACL2 sources, for example
 replacing @('(null lst)') by @('(endp lst)') in a function's definition in
 support of the termination proof and then specifying @('(true-listp lst)') in
 its guard.  You don't need to become a system developer to do this, but see
 @(see developers-guide) if you are an experienced ACL2 user and system
 development interests you.  IMPORTANT: Eventually you will probably want to
 undo your changes; this will be explained further below.</p>

 <p>After making such changes, build an ACL2 executable image containing your
 modified code, to test that the modified code builds.  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>In general, in this new file or new file addition, it is necessary to use
 both @(tsee verify-termination) and @(tsee verify-guards) on the system
 functions in question, in order to both put them in logic mode and verify their
 guards. However, as explained in the documentation of @(tsee
 verify-termination), sometimes @(tsee verify-termination) also verifies the
 guards (see also @(tsee set-verify-guards-eagerness)).  In this case, it is
 good practice to add a comment `@('; and guards')' just after the @(tsee
 verify-termination) form, on the same line, as can be seen in some of the files
 under @(see community-books) directory @('system/').</p>

 <p>Now it is time to add entries to the value of constant
 @('*system-verify-guards-alist*') in your local copy of the ACL2 sources,
 which specifies functions whose guard-verification is completed by including
 @(see community-book) @('books/system/devel-check.lisp') (which includes
 @('books/system/top.lisp').  Each entry is of the form @('(function-symbol
 . measure)').  For example, the entry @('(ARITY-ALISTP ACL2-COUNT ALIST)')
 signifies that the function symbol @('arity-alistp') is to have measure
 @('(acl2-count alist)'), while the entry @('(ARGLISTP)') signifies that
 function symbol @('arglistp') has no measure (i.e., we use @('nil') for the
 measure), presumably because its definition is not recursive.  After you make
 those additions, then 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 seems to have worked, for example by finding the
 string @('"Successfully built"') near the end of your log file.</li>

 <li>Run a ``devel'' regression, for example as follows if starting in the ACL2
 sources directory.  Note that including ``@('ACL2_USELESS_RUNES= ')'' as shown
 below may be necessary because of how proofs differ between normal and
 ``devel'' versions of ACL2.

 @({
 make clean-books ACL2=`pwd`/saved_acl2d
 cd books
 (time nice make -j 8 \
            ACL2=`pwd`/../saved_acl2d \
            ACL2_USELESS_RUNES= \
            system/devel-check.cert) \
   >& make-devel-regression.log&
 })

 The last of these commands should run much more quickly than a normal
 regression.  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.

 @({
 SUCCESS for chk-new-verified-guards
 SUCCESS for check-system-events
 SUCCESS for devel-check
 })</li>

 <li>Now clean the books (see @('make clean-books') above) and then do a normal
 build and regression.</li>

 <li>Finally, send your changes to Matt Kaufmann, with a request that they be
 incorporated into the ACL2 sources and books.</li>

 </ol>

 <p>We now return to the remark labeled ``IMPORTANT'' above: undoing your
 changes.  This isn't necessary if you will not be using that local copy of
 ACL2 in the future.  But otherwise you may run into problems when you try to
 use git to merge changes into that local ACL2+books copy.  One option is to
 throw your changes away by standing in your local ACL2 directory and using the
 shell command: @('git checkout -f').  But be careful &mdash; this will throw
 away all your work!  So you might want to wait until your changes make it into
 the main (master) git branch.</p>")
other
(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, which does not evaluate its argument, provides output
 showing the guard proof obligation (also known as the guard theorem) as
 printed by @('verify-guards'), but without then carrying out a proof attempt.
 See also @(see guard-formula-utilities) for related utilities.</p>

 @({
  Example Forms:
  (verify-guards-formula foo)
  (verify-guards-formula foo :guard-debug t)
  (verify-guards-formula foo :guard-debug t :guard-simplify :limited)
  (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') and @(':guard-simplify'), which have the same effect as in
 @(tsee verify-guards) (also see @(see guard-debug) and @(see
 guard-simplification)), 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>")
other
(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>It may be necessary to specify an appropriate @(':ruler-extenders') in a
 @('dcl') supplied to @('verify-termination').  This determines the @(see
 rulers) used in the termination proofs and also the case analysis in the
 induction scheme suggested by the admitted function.  See @(see
 induction-coarse-v-fine-grained).</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*'), which specifies 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>")
other
(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.  This restriction is important in general for preserving soundness; see
 @(see program-only).  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)
 ; In the following, t can be replaced by an expression that evaluates to a
 ; list of symbols for which it is permitted to verify termination.
 (assign verify-termination-on-raw-program-okp t)
 })")
other
(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>")
other
(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>")
other
(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:
  1, 2, ..., up, nx, bk, pp, (pp n), (pp lev len), =, (= symb),
  (cmds c1 c2 ... cn), and q.
 })

 <p>In the interactive @('walkabout') loop, a positive integer n takes you to
 the nth position, while @('up') 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').  The commands @('=') and @('cmds') are described
 below.</p>

 <p>Note that the commands above work in any package: @('up'), @('nx'),
 @('bk'), @('pp'), @('='), @('cmds'), and @('q') are converted to the
 @('"ACL2"') package if the current package is not @('"ACL2"').  Also, as a
 convenience, the single character @('0') is accepted as equivalent to
 @('up').</p>

 <p>The following example illustrates the commands described above.</p>

 @({
  ACL2 !>(walkabout (append '(a (b1 b2 b3)) '(c d e f)) state)

  Commands:
  1, 2, ..., up, nx, bk, pp, (pp n), (pp lev len), =, (= symb),
  (cmds c1 c2 ... cn), and q.

  (A (B1 B2 B3) C ...)
  :2
  (B1 B2 B3)
  :3
  B3
  :up
  (B1 B2 B3)
  :nx
  C
  :nx
  D
  :up
  (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>The command @('(cmds c1 c2 ... cn)') just executes each of the @('ci'),
 sequentially.</p>

 <p>The command @('q') simply causes an exit from the
 @('walkabout') loop.</p>

 <p>The command @('=') also exits, but returns the current object as the value in
 an ACL2 @(see error-triple).</p>

 <p>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>

 @({
  ...
  :pp
  (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:
  1, 2, ..., up, nx, bk, pp, (pp n), (pp lev len), =, (= symb),
  (cmds c1 c2 ... cn), and q.

  (C D E . F)
  :3
  E
  :nx
  .
  :nx
  F
  :up
  (C D E . F)
  :4
  .
  :up
  (C D E . F)
  :5
  F
  :
 })")
other
(defxdoc warnings
  :parents (output-controls)
  :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.  See also @(tsee toggle-inhibit-warning) and
 @(tsee set-warnings-as-errors).</p>")
other
(defxdoc warrant
  :parents (apply$)
  :short "Giving @(tsee apply$) permission to handle a user-defined function in proofs"
  :long "<p>The word ``warrant'' is defined in the Merriam-Webster dictionary
  as ``a commission or document giving authority to do something....''</p>

  <p>The discussion below mentions the concept of @(tsee badge)s, which are
  easily confused with warrants.  See the discussion of <b>Badges versus
  Warrants</b> at the top of @(tsee defbadge).  But roughly put, badges extend
  the ACL2 syntax and warrants extend the proof theory.  You'll need a badge
  for @('fn') to allow the system to syntactically analyze @('(apply$ 'fn
  ...)').  You'll need a both a badge and a warrant for @('fn') if you wish to
  reason about that term with ACL2.  Badges and warrants also have impact on
  evaluation of forms in the top-level loop.  See @(see
  guarantees-of-the-top-level-loop).</p>

  <p>In the ACL2 proof theory, the functions @(tsee badge) and @(tsee apply$)
  are undefined on user-defined function symbols.  To be precise, when
  presented with a user-defined function symbol, @('badge') calls the weakly
  constrained function @('badge-userfn') and @('apply$') calls the weakly
  constrained function @('apply$-userfn').  Warrants are terms that, if
  available as hypotheses in a conjecture, further constrain those functions
  for specific function symbols.  If there is a warrant for @('fn') among the
  hypotheses of a conjecture, @('(badge 'fn)') and @('(apply$ 'fn ...)')  can
  be simplified appropriately.  In particular, @('(badge 'fn)') is simplified
  to the actual badge of @('fn') and @('(apply$ 'fn ...)') is simplified to the
  appropriate application of @('fn') provided the arguments are suitably @(see
  tame).  We think of the warrant for @('fn') giving @('badge') and @('apply$')
  authority to expand on @(''fn').  For reasons of logical consistency not
  every @('fn') can have a warrant.  Warrants are issued, when possible, by
  @(tsee defwarrant).</p>

  <p>In the ACL2 evaluation theory &mdash; a consistent extension of the proof
  theory &mdash; all warrants issued by @('defwarrant') are implicitly assumed,
  meaning @('badge') and @('apply$') can be executed on warranted user-defined
  function symbols at the top-level of the ACL2 loop without explicit mention
  of the warrants.  In fact, just as the evaluation theory can &mdash;
  ``magically'' &mdash; execute @(':program') mode functions despite the
  absence of any axioms about them, the evaluation theory can execute a
  well-formed @('apply$') on any @(':program') mode function that has a @(tsee
  badge).  However, for a @(':logic') mode function @('fn'), the top-level loop
  cannot evaluate @('(apply$ 'fn ...)')  unless @('(defwarrant fn)') has
  previously succeeded.  See @(see guarantees-of-the-top-level-loop).)  For a
  discussion of the restrictions on when a @('fn') can be warranted, see @(tsee
  defwarrant).  This topic discusses warrants <i>per se</i>, their names, their
  logical meaning, when they must be explicitly added as hypotheses to
  conjectures, and their consistency.</p>

  <h3>Logical Definition of the Warrant of a Function</h3>

  <p>If <i>fn</i> has a warrant, then the warrant is the term
  <tt>(apply$-warrant-</tt><i>fn</i><tt>)</tt>, i.e., a call of the 0-ary
  warrant function named, <tt>apply$-warrant-</tt><i>fn</i>.  That warrant
  function name is admitted to the logic when @('defwarrant') succeeds on
  @('fn').</p>

  <p>The warrant function for @('fn'), introduced by @('(defwarrant fn)'), is
  defined with @(tsee defun-sk) because the warrant must specify the values
  returned by <tt>(apply$ 'fn args)</tt> <i>for all possible</i> @('args').
  Recall that @(tsee badge) and @(tsee apply$) defer to two undefined
  functions, @('badge-userfn') and @('apply$-userfn'), when they are applied to
  user-defined function symbols.  The warrant for @('fn') is actually phrased
  in terms of those two undefined functions.  By stipulating their values on
  @(''fn') the warrant determines the values of @('(badge 'fn)') and @('(apply$
  'fn ...)').  To create the warrant function for @('fn'), @('defwarrant')
  must turn the ilks of @('fn') into tameness requirements on the corresponding
  elements of the @('args') to which @('fn') will be applied by @('apply$').
  Each @(':FN') argument must be a @(see tame) function and each @(':EXPR')
  argument must be a @(see tame) expression.</p>

  <p>It is easiest to understand the above paragraph by looking at the
  generated warrant function for @('foldr'), whose definition is shown at the
  top of the documentation for @(tsee apply$) and whose @(see badge) is
  @('(APPLY$-BADGE 3 1 NIL :FN NIL)'), indicating that @('foldr') takes 3
  arguments of ilks @('NIL'), @(':FN'), and @('NIL'), and returns 1 result.
  The warrant function for @('foldr') is defined as follows.</p>

  @({
  (defun-sk apply$-warrant-foldr ()
    (forall (args)
      (implies (tamep-functionp (cadr args))
               (and (equal (badge-userfn 'FOLDR)
                           '(APPLY$-BADGE 3 1 NIL :FN NIL))
                    (equal (apply$-userfn 'FOLDR args)
                           (foldr (car args)
                                  (cadr args)
                                  (caddr args))))))
    :constrain t)
  })

  <p>Notice also that the tameness hypothesis involves the universally
  quantified variable @('args'), but that the first conjunct of the conclusion
  does not mention that variable.  So we can read @('(apply$-warrant-foldr)')
  as equivalent to the conjunction of:</p>

  @({
  (equal (badge-userfn 'FOLDR)
         '(APPLY$-BADGE 3 1 NIL :FN NIL))
  })

  <p>and</p>

  @({
  (forall (args)
      (implies (tamep-functionp (cadr args))
               (equal (apply$-userfn 'FOLDR args)
                      (foldr (car args)
                             (cadr args)
                             (caddr args)))))
  })

  <p>The first specifies the value of the undefined function used by @('badge')
  to find the badge of a user-defined function.  The second specifies the
  behavior of the undefined function used by @('apply$') to @('apply$')
  <tt>'FOLDR</tt> and requires that the second element of @('args') be a @(see
  tame) function.</p>

  <p>Finally, notice that the warrant function for @('foldr'),
  @('apply$-warrant-foldr'), ancestrally depends on @('foldr'): @('foldr') is
  called in the @('defun-sk').  That is crucial to avoiding the @('LOCAL')
  problem noted in @(see introduction-to-apply$).  If the warrant for
  @('foldr') is required for a theorem's proof (which it will be if the proof
  involves ``expanding'' @('(apply$ 'FOLDR ...)')), then the theorem is
  ancestrally dependent on @('foldr') even though that function symbol may not
  be otherwise mentioned in the theorem.  That, in turn, means that @('foldr')
  may not be a locally defined symbol in the environment from which the theorem
  is exported.</p>

  <p>Now consider a function symbol that returns more than one result.  Suppose
  the badge of @('add-and-subtract') is @('(APPLY$-BADGE 2 2 . T)'), meaning it
  takes two ordinary objects and returns two results.  The function is tame and
  so no tameness requirements are imposed on its application.  Its warrant is
  defined</p>

  @({
  (defun-sk apply$-warrant-add-and-subtract ()
    (forall (args)
      (and (equal (badge-userfn 'add-and-subtract)
                  '(APPLY$-BADGE 2 2 . T))
           (equal (apply$ 'add-and-subtract args)
                  (mv-list 2
                           (add-and-subtract (car args) (cadr args)))))))
  })

  <h3>Rewrite Rules that Lift and Force the Warrant</h3>

  <p>Once @('defwarrant') has introduced the warrant function for <i>fn</i> it
  proves two rewrite rules, conjoined under the name <tt>apply$-</tt><i>fn</i>,
  that ``lifts'' the warrant from the level of the two undefined functions to
  the level of @('badge') and @('apply$').  In the case of @('foldr') the rules
  are:</p>

  @({
  (defthm apply$-foldr
    (and (implies (force (apply$-warrant-foldr))
                  (equal (badge 'FOLDR)
                         '(APPLY$-BADGE 3 1 NIL :FN NIL)))
         (implies (and (force (apply$-warrant-foldr))
                       (tamep-functionp (car (cdr args))))
                  (equal (apply$ 'FOLDR args)
                         (foldr (car args)
                                (car (cdr args))
                                (car (cdr (cdr args))))))))
  })

  <p>Observe that these rules say that if @('(apply$-warrant-foldr)') is
  available as a hypothesis, then @('(badge 'FOLDR)') is @('(APPLY$-BADGE 3 1
  NIL :FN NIL)') and @('(apply$ 'FOLDR args)') has the naively expected
  behavior of calling @('foldr'), provided the second element of @('args') is a
  @('tamep-functionp').  Also note that the warrant hypothesis is @(tsee
  force)d in both rules.</p>

  <p>The effect of these rules is if either @('(badge 'FOLDR)') or any instance
  of @('(apply$ 'FOLDR args)') arises during a proof, the warrant for
  @('foldr') is raised and either relieved or forced.  The @('badge') and
  @('apply$') terms are simplified whether the warrant is present or not, but
  if the warrant is not among the hypotheses and the proof is otherwise
  successful, the warrant for @('foldr') will show up in a checkpoint.</p>

  <p>If no warrant has been issued for @('foldr') these terms will not
  simplify.</p>

  <h3>Determining the Necessary Warrants</h3>

  <p><i>There is no easy way to determine the warrants you'll need to make a
  formula a theorem.</i>  At first this seems to be a problem that could be solved
  with a few rules of thumb and indeed, there are a few useful rules.  But they
  don't guarantee success.</p>

  <p><i>Rule 1.</i> One way to determine sufficient warrants for a formula to
  be a theorem is to attempt to prove the formula without warrants and see the
  checkpoints.  This may have to be repeated to collect sufficient warrants and
  can be frustrating.  Furthermore, as illustrated further below, it can lead
  to unnecessary warrants.</p>

  <p>Most users attempt to anticipate what warrants are needed.</p>

  <p><i>Rule 2.</i> You will probably need a warrant hypothesis for every
  user-defined function symbol mentioned in the fully translated term occupying
  any slot of ilk @(':FN') in the formula you're trying to prove.  The two
  common situations are quoted user-defined function symbols in such slots and
  @(tsee lambda$) expressions.  In the latter case, you must consider every
  user-defined function symbol in the <i>fully translated</i> body of the
  @(tsee lambda$) expression.  (If you've ignored our recommendations to use
  @('lambda$') instead of hand-typed quoted @('LAMBDA') objects, you'll have to
  look at those too.)</p>

  <p>But Rule 2 says ``probably need a warrant'' because whether you do or not
  depends on what you're proving.  In the examples below, suppose we have
  carried out these events.</p>

  @({
  (include-book "projects/apply/top" :dir :system)

  (defun$ sq (x) (* x x))
  })

  <p>and recall that @('collect$') is @(tsee loop$) scion logically defined
  as</p>

  @({
  (defun$ collect$ (fn lst)
    (if (endp lst)
        nil
        (cons (apply$ fn (list (car lst)))
              (collect$ fn (cdr lst)))))
  })

  <p>No warrant is <i>really</i> needed to prove</p>

  @({
  (thm (equal (collect$ 'sq (append a b))
              (append (collect$ 'sq a) (collect$ 'sq b))))
  })

  <p>because it <i>could</i> be proved by appealing to the more general</p>

  @({
  (thm (equal (collect$ fn (append a b))
              (append (collect$ fn a)
                      (collect$ fn b))))
  })

  <p>which makes clear that the properties of @('sq') are totally irrelevant to
  the proof of this formula.</p>

  <p>But if you followed Rule 1 and just submitted</p>

  @({
  (thm (equal (collect$ 'sq (append a b))
              (append (collect$ 'sq a)
                      (collect$ 'sq b))))
  })

  <p>the proof would fail with a checkpoint indicating that you need the
  warrant for @('sq').  That happens because the :rewrite rules proved by
  @('defwarrant'), discussed in the previous section and named @('apply$-sq')
  in the case of @('sq'), fire and force that warrant.  However, you could
  disable that rule and get the proof without a warrant.</p>

  <p>To further dim our hopes for a simple way to identify warrants,
  consider</p>

  @({
  (defun$ square (i) (apply$ 'sq (list i)))
  })

  <p>and then the proof of</p>

  @({
  (thm (equal (square i) (* i i)))
  })

  <p>This theorem requires the warrant for @('sq') even though @(''sq') is not
  mentioned in the top-level statement of the theorem.  The problem, of course,
  is that the mention of @(''sq') in a @(':FN') slot is mentioned in the
  definition of @('square').</p>

  <p><i>Rule 3.</i> You may need warrants for any symbols used in @(':FN')
  slots in the definitions of any function appearing in the formula.</p>

  <p>And then of course there is the usual reason you need forgotten
  hypotheses: some lemma critical to your proof has that hypothesis.</p>

  <p>For example, one could imagine proving</p>

  @({
  (defthm lemma
    (implies (apply$-warrant-sq)
             (equal (square x) (sq x))))
  })

  <p>and then try to prove</p>

  @({
  (thm (equal (square x) (* x x))
       :hints (("Goal" :in-theory (disable square))))
  })

  <p>hoping the lemma would reduce @('(square x)') to @('(sq x)') and then
  @('(sq x)') would expand to @('(* x x)').  But of course, the lemma isn't
  applicable because we can't establish its hypothesis.  The point here is that
  another source of required warrants can be the warrant hypotheses of any
  lemmas needed for the proof.  We could posit a ``Rule 4'' but what's the
  point?</p>

  <p>Returning to the first thing we said in this section, there is no easy
  sure-fire way to determine the warrants you'll need.  It just depends on the
  functions you're manipulating, the cases explored in the proof, the
  hypotheses of crucial lemmas, etc.  However, our experience is that it's not
  nearly so hard as we're suggesting here!</p>

  <p>Basically you'll need a warrant for @('fn') if the proof requires
  @('apply$') to behave as naively expected on @(''fn') or the warrant is
  required for some lemma.  Chances are you'll know when you're depending on
  the meaning of a quoted symbol and when you're not.  And Rule 1 will
  eventually get you there though it may generate unnecessary warrant
  hypotheses.</p>

  <p>There is another piece of good news perhaps best explained by example.</p>

  <p>Imagine that you've defined and warranted your own versions of the
  familiar list concatenation and list reverse functions under the names
  @('ap') and @('rv').</p>

  @({

  (defun$ ap (x y)
    (if (endp x)
        y
        (cons (car x)
              (ap (cdr x) y))))

  (defun$ rv (x)
    (if (endp x)
        nil
        (ap (rv (cdr x))
            (list (car x)))))
  })

  <p>What warrant(s) do you need to prove</p>

  @({
  (implies (true-listp x)
           (equal (apply$ 'rv (list (apply$ 'rv (list x)))) x))?
  })

  <p>You clearly need the warrant for @('rv').  But do you need the warrant for
  its subfunction @('ap')?  Some users fall into the trap of thinking they do.
  They think they'll need warrants for all the subfunctions of any function
  requiring a warrant.  We fall into this trap when we think <i>all
  evaluation</i> is carried out by @('ev$') and @('apply$').  Put another way,
  if we defined</p>

  @({
  (defun$ rv1 (x)
    (if (endp x)
        nil
        (apply$ 'ap
                (list (rv1 (cdr x))
                      (list (car x))))))
  })

  <p>and then tried to prove</p>

  @({
  (implies (true-listp x)
           (equal (apply$ 'rv1 (list (apply$ 'rv1 (list x)))) x))
  })

  <p>we would indeed need warrants for both @('rv1') and @('ap'), as per Rule
  3, because @('rv1') @('apply$')s @(''ap').</p>

  <p>But the warrant for the original @('rv') says that @('(apply$ 'rv args)')
  is (unconditionally) equal to @('(rv (car args))').  There are no
  @('apply$')s left in the problem once we get to a call of the ACL2 function
  @('rv').  We don't need any warrants, even to evaluate a function we called
  via @('apply$') unless the definition of the function itself involves further
  @('apply$')s.</p>

  <h3>A Convenient Macro for Conjoining Warrants</h3>

  <p>Because ``<tt>APPLY$-WARRANT-</tt><i>fn</i>'' is hard to remember, we
  provide a macro for referring to the conjunction of warrant terms for a list
  of functions.</p>

  @({
  General Form:
  (warrant fn1 fn2 ... fnk)
  })

  <p>where each @('fni') is the name of a defined function on which
  @('defwarrant') has been previously called and succeeded.  (Actually, we
  allow the @('fni') to include certain primitive function symbols already
  built into @('apply$'), but for the moment we ignore the possible presence of
  such symbols among the arguments to @('warrant').)  @('(Warrant fn1 fn2
  ... fnk)') expands to:</p>

  @({
  (AND (FORCE (APPLY$-WARRANT-fn1))
       (FORCE (APPLY$-WARRANT-fn2))
       ...
       (FORCE (APPLY$-WARRANT-fnk)))
  })

  <p>Because there are over 800 ACL2 primitives built into @('apply$'), it can
  be hard to look at a conjecture involving, say, a @(tsee lambda$) term, and
  list all and only the function names that need warrants.  For example, if the
  body of the @('lambda$') term calls @('logeqv') it will expand into
  @('binary-logeqv') and the diligent user might anticipate, accurately, that
  the @('ev$') of that body will involve @('(apply$ 'BINARY-LOGEQV ...)') and
  thus might suppose that @('binary-logeqv') be included among the @('fni')
  listed in the @('warrant') hypothesis.  But no warrant for @('binary-logeqv')
  exists, that is, @('apply$-warrant-binary-logeqv') is not defined, because
  @('binary-logeqv') is built into @('apply$').  For this reason, we do not
  insist that every @('fni') in @('warrant')'s argument be a function
  possessing a warrant.  Instead, the @('warrant') macro ignores those @('fni')
  built into @('apply$').  It does cause an error if one of the @('fni') has no
  warrant and is not built in.</p>

  <p>The @('(warrant fn1 fn2 ... fnk)') macro @(tsee force)s the warrants
  because (a) we assume the only use of the macro is to add warrant hypotheses
  to conjectures and (b) by forcing warrants aggressively the prover ``almost
  completes'' more proofs and enters a forcing round that highlights the need
  to assume those warrants.  When a rewrite rule, for example, is conditioned
  on a warrant that is not forced (as would happen if you added the hyps
  @('(apply$-warrant-fn1)'), @('(apply$-warrant-fn2)'), etc.), then the rule
  will not fire if a subsequent conjecture omitted the warrants.  Of course,
  this raises the question ``But are all the warrants really true?''</p>

  <h3>Why Warrants Don't Render Theorems Vacuous</h3>

  <p>Adding warrants to formulas certainly restricts (weakens) the resulting
  theorem since it is only applicable when the warrant is assumed.  But an
  important question to ponder is whether adding warrants can actually make a
  formula vacuously valid?  That is, can a set of warrants simply be
  unsatisfiable so that any formula having that set of warrants among its
  hypotheses is a theorem?  Put another way, is there a model for the set of
  all warrants introduced by @(tsee defwarrant)?</p>

  <p>The answer is yes.  This is discussed in <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.  For any set of functions warranted by @('defwarrant')
  it is possible to <i>define</i>, under the standard ACL2 definitional
  principle, versions of those functions (together with @('apply$'), @('ev$'),
  etc.) and then make attachments to the undefined @('badge-userfn') and
  @('apply$-userfn'), and so that every warrant is provably equal to @('T').
  In fact, the resultant theory is the basis of ACL2's evaluation theory where
  all warranted functions can be @('apply$')d (under the appropriate tameness
  requirements) without explicit mention of warrants.  The crux of the proof is
  admitting a big mutually recursive clique containing versions of @('apply$')
  and all of its @(see scion)s, by inventing a measure that provably decreases
  as @('apply$') and the scions call each other.  The keys to that measure's
  existence are the restrictions imposed by @(tsee defwarrant) and @(see
  tame)ness.  See the paper for a sketch of the proof and see the comment
  titled <tt>Essay on Admitting a Model for Apply$ and the Functions that Use
  It</tt> in the ACL2 source file @('apply-raw.lisp').</p>")
other
(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>")
other
(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>")
other
(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>")
other
(defxdoc well-formed-lambda-objectp
  :parents (apply$)
  :short "Predicate for recognizing well-formed @('LAMBDA') objects"
  :long "@({
  Example:                                    value
  (well-formed-lambda-objectp                   T
   '(lambda (x) (binary-+ '1 x))
   (w state))

  (well-formed-lambda-objectp                   NIL
   '(lambda (x) (+ 1 x))
   (w state))

  (well-formed-lambda-objectp                   T
   '(lambda (x)
      (declare (type (satisfies natp) x)
               (xargs :guard (natp x)
                      :split-types t))
      (binary-+ '1 x))
   (w state))

  (well-formed-lambda-objectp                   NIL
   '(lambda (x)
      (declare (type (satisfies natp) x))
      (binary-+ '1 x))
   (w state))

  General Form:
  (well-formed-lambda-objectp obj wrld)
  })

  <p>@('Well-formed-lambda-objectp') is a @(':program') mode function that
  checks the well-formedness of an arbitrary ACL2 object being used as a
  @('LAMBDA') object by @(tsee apply$).</p>

  <p>Before we tell you what ``well-formedness'' means in this context we
  collect some random related facts that we consider more important than its
  precise meaning!</p>

  <p>@('Lambda$') terms always translate to quoted well-formed @('LAMBDA')
  objects unless translate signals an explanatory error.  Don't try to type
  well-formed @('LAMBDA') objects as explicitly quoted constants.  Use @(tsee
  lambda$)!</p>

  <p>Only well-formed @('LAMBDA') objects can be compiled.  Use @(tsee
  lambda$).</p>

  <p>But the compiled code is not necessarily always run when a well-formed
  @('LAMBDA') object is @('apply$')d!  The object must additionally be guard
  verified and its guards must be satisfied by the arguments supplied by
  @('apply$').  Well-formedness does not do guard verification.</p>

  <p>The definitional axiom for @(tsee apply$) knows nothing about
  well-formedness.  It checks that the purported @('LAMBDA') object satisfies
  @(tsee tamep-lambdap), which is a simpler @(':logic') mode concept.  If you
  are writing a definition or theorem about an arbitrary object to be used as a
  @('LAMBDA') object by @('apply$'), and want to restrict it to the kind of
  objects handled as @('LAMBDA') objects by @('apply$'), use the predicate
  @('tamep-lambdap') to characterize the object.  (Since
  @('well-formed-lambda-objectp') is in @(':')@(tsee program) mode and requires
  access to the world, using it in a @(':logic') mode context would involve a
  lot of work!)</p>

  <p>Well-formedness implies tameness.  So if you write your @('LAMBDA')
  objects with @('lambda$') @('apply$') will be able to handle them. But
  @('apply$') can handle more objects than the Common Lisp compiler can.  Some
  tame @('LAMBDA') objects can be applied faster than others.  The fast ones
  are recognized by @('well-formed-lambda-objectp') -- but also have to be
  guard verified and guard checked.  Applications of ill-formed but tame
  @('LAMBDA') objects are evaluable, but the evaluation is done more slowly.
  See the performance comparison in @(tsee print-cl-cache).</p>

  <p>We compare well-formedness to tameness at the end of this topic.</p>

  <p>You can't call this predicate on a @('lambda$') term, as by</p>

  @({
  (well-formed-lambda-objectp (lambda$ (x) x) (w state))
  })

  <p>because @('lambda$') can only be called in slots of ilk @(':FN').
  Furthermore, there's no point!  @('Lambda$') terms always translate to
  well-formed @('LAMBDA') objects unless an explanatory error is signaled by
  translation.</p>

  <p>If you want to <i>see</i> the translation of a @('lambda$') term, e.g., to
  copy the text and modify it to produce some similar @('LAMBDA') object,
  use @(':')@(tsee translam).  We sometimes do this to explore by example the
  restrictions on well-formedness.</p>

  <p>If you have a @('LAMBDA') object, e.g., one printed by @(tsee
  print-cl-cache), that you suspect is ill-formed, this function won't tell you
  <i>why</i> it is ill-formed!  It will just tell you whether it's ill-formed.
  If you want to know why, translate the quoted @('LAMBDA') object with
  @(':')@(tsee translam), which generates sometimes verbose error messages.</p>

  <p>The global setting of @('set-ignore-ok') has no effect on well-formedness
  of @('LAMBDA') objects.  @('IGNORE') and @('IGNORABLE') declarations inside the
  @('LAMBDA') are effective.</p>

  @({
  ACL2 !>(set-ignore-ok t)
  T
  ACL2 !>(well-formed-lambda-objectp
          '(LAMBDA (X Y)
             (DECLARE (XARGS :GUARD (NATP X) :SPLIT-TYPES T))
             (BINARY-+ '1 X))
          (w state))
  NIL

  ACL2 !>(well-formed-lambda-objectp
          '(LAMBDA (X Y)
             (DECLARE (XARGS :GUARD (NATP X) :SPLIT-TYPES T)
                      (IGNORE Y))
             (BINARY-+ '1 X))
          (w state))
  T
  })

  <p>There should be very few occasions on which you need to know what this
  predicate checks!</p>

  <p>That said, here are the rules enforced.</p>

  <p>An object is a well-formed @('LAMBDA') object iff it has one of the
  following two forms:</p>
  <code>
  (LAMBDA vars tbody)          ; ``simple''  LAMBDA object
  (LAMBDA vars tdcl tbody)     ; ``declared'' LAMBDA object
  </code>

  <p>where</p>

  <ul>
  <li>@('vars') is a list of distinct legal variable names</li>

  <li>@('tdcl'), if present, is a @('DECLARE') form containing, at most,
      @('TYPE'), @('IGNORE'), @('IGNORABLE'), and @('XARGS') keys.  The user of
      @(tsee lambda$) may provide multiple @('DECLARE') forms but when
      translated they are combined into one as shown here.</li>

  <li>If an @('XARGS') key is present it has exactly this form @('(XARGS
      :GUARD tguard :SPLIT-TYPES T)'), where @('tguard') is a <i>fully
      translated</i> logic mode term involving only the formal variables,
      @('vars').  Note that the user of @(tsee lambda$) may supply
      @(':SPLIT-TYPES') @('NIL') and may do so before or after the @(':GUARD'),
      and the guard term need not be in translated form, but the resulting
      @('LAMBDA') object has the form described here.</li>

  <li>The @(':GUARD') specified in @('XARGS') must include as a conjunct
      every @('TYPE') expression generated by any @('TYPE') specs.  E.g.,
      @('(INTEGERP x)') must be a conjunct of @('tguard') if @('(TYPE INTEGER
      ... x ...)') is declared.  That is consistent with the @(':SPLIT-TYPES')
      @('T') setting and means the guard does not need to be extended any
      further with the @('TYPES').  The point of this restriction is to
      guarantee that the guard implies the types declared to the compiler.  But
      this is a purely syntactic check and so may at times require entering
      silly-looking guards.  For example, @('(declare (type rational x) (xargs
      :guard (integerp x) :split-types t))') is ruled ill-formed because
      @('(rationalp x)') is not a conjunct of the guard, even though it is
      logically implied by the guard.  So you'd have to use @('(declare (type
      rational x) (xargs :guard (if (integerp x) (rationalp x)
      'nil) :split-types t))').  Note also that the guard is a fully translated
      conjunction, i.e., an @('IF'), not an @('AND')!  Order of the conjuncts
      does not matter.<p/>

      Note: The guard need not be tame (or even fully badged) because guards
      are irrelevant to the axioms of @('apply$').  But guards must be in
      @(':logic') mode from the outset because we may have to prove guard
      obligations on-the-fly in evaluation (we do not want to try to convert
      functions used in the guard from from @(':program') to @(':logic') mode
      while doing an evaluation of an @('apply$')).</li>

  <li>@('tbody') is a fully translated, @(see tame) term, involving no free
      variables and respecting the declared @('IGNORE') and @('IGNORABLE')
      declarations.<p/>

      Furthermore, in the case of a lambda object generated by @('lambda$'),
      @('tbody') is a ``tagged'' version of the translation of the body used in
      the @('lambda$') expression.  Tagging involves use of a special form
      generated by @('tag-translated-lambda$-body') and recognized by
      @('lambda$-bodyp').  This form contains the untranslated @('lambda$')
      expression as well as the translation of its body.  For example,
      @('(lambda$ (x) (+ 1 x))') translates to the tagged lambda object
      @(''(LAMBDA (X) (RETURN-LAST 'PROGN 'orig-form tbody))'), where
      @('orig-form') is @('(LAMBDA$ (X) (+ 1 X))') and @('tbody') is
      @('(BINARY-+ '1 X)').<p/>

      It may be helpful to use @(':')@(tsee translam) to inspect examples of
      the translations of @('lambda$') expressions.</li>

  </ul>

  <h3>The Differences Between Well-Formed and Merely Tame Lambda Objects</h3>

  <p>Roughly put, tame @('LAMBDA') objects have to have one of the two basic
  shapes described above (simple or declared), the listed formals merely have
  to be symbols -- not necessarily variable symbols and not necessarily
  distinct.  The declaration, if present, is completely irrelevant and the body
  merely has to be a tame expression -- not necessarily closed with respect to
  the formals or respecting @('IGNORE') or @('IGNORABLE') declarations.  The
  meaning assigned to such an object when applied to some arguments is just the
  result delivered by @('ev$') under an alist formed by pairing the formals --
  including non-variables and any duplicates -- with the actuals.  If a free
  variable is encountered, @('ev$') gives it the value @('NIL') courtesy of
  @('assoc').</p>

  <p>This behavior is implemented by compiled Common Lisp only when
  well-formedness, guard verification, and guard checking approve of the object
  and its application.</p>")
other
(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>")
other
(defxdoc well-founded-relation
  :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,
 @('get-well-founded-relation'), may be found in the @(see community-books), file
 @('std/system/get-well-founded-relation.lisp').</p>")
other
(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 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 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>")
other
(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>

 <h3>Summary Documentation</h3>

 @({
  General Form:
  (wet form           ; an arbitrary form
       :book bk-form  ; optional, not evaluated; specify different wet book
       ;;; the rest are optional and evaluated:
       :compile c     ; :same, t, or nil; default :same (nil if :fns supplied)
       :fullp h       ; nil by default, else handle some raw Lisp errors
       :evisc-tuple e ; an evisc-tuple
       :fns fns       ; :all, or a list of functions to show in a backtrace
 })

 <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.</p>

 <h3>Discussion</h3>

 <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.  (Technical detail: by default the global abbrev-evisc-tuple
 is used, if bound; see @(see set-evisc-tuple).  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>

 <h3>Keyword Arguments</h3>

 <p>The @(':fullp') option.  Consider the following example.</p>

 @({
 (program)
 (defun foo (x) (declare (xargs :guard (consp x))) (car x))
 (defun bar (x) (foo (cdr x)))
 (defun g (x) (bar (cdr x)))
 ; Raw Lisp error:
 (g '(3 4 . 5))
 })

 <p>We may be initially disappointed using @('wet') on this example, as follows
 &mdash; it didn't work!</p>

 @({
 ACL2 p!>(wet (g '(3 4 . 5)))

 TTAG NOTE: Adding ttag :TRACE! from the top level loop.

 ***********************************************
 ************ ABORTING from raw Lisp ***********
 ********** (see :DOC raw-lisp-error) **********
 Error:  Fault during read of memory address #x2D
 While executing: FOO
 ***********************************************

 The message above might explain the error.  If not, and
 if you didn't cause an explicit interrupt (Control-C),
 then it may help to see :DOC raw-lisp-error.

 To enable breaks into the debugger (also see :DOC acl2-customization):
 (SET-DEBUGGER-ENABLE T)
 ACL2 p!>
 })

 <p>The fix is to use @(':fullp t').</p>

 @({
 ACL2 p!>(wet (g '(3 4 . 5)) :fullp t)

 TTAG NOTE: Adding ttag :TRACE! from the top level loop.


 ACL2 Error in WET:  The guard for the :program function call (FOO X),
 which is (CONSP X), is violated by the arguments in the call (FOO 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.


 Backtrace stack:
 ----------------
 1. (ACL2_*1*_ACL2::FOO 5)
 2. (ACL2_*1*_ACL2::BAR (4 . 5))
 3. (ACL2_*1*_ACL2::G (3 4 . 5))

 ACL2 p!>
 })

 <p>Why doesn't @('wet') always do things this way?  The answer pertains to
 performance.  When @(':fullp') is non-nil, @('wet') sets guard-checking to
 @(':all') before evaluating the given form; see @(see set-guard-checking).
 This may slow down evaluation substantially, which is why it is not the
 default behavior.</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>

 <h3>Concluding Remark</h3>

 <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>")
other
(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>")
other
(defxdoc windows-installation
  :parents (installation-support)
  :short "Installing ACL2 on Windows"
  :long "<p>Windows users will probably want to do one of the following to
 install and run ACL2 on their systems.  Thanks to David Rager for his help
 with this topic.</p>

 <ul>

 <li>Use a Virtual Machine platform, such as VMware Player (free for
 non-commercial use) or Oracle Virtualbox (free even for commercial
 use) to install Linux, and then follow the normal
 @(see installation-instructions) to install ACL2.  As of 2014, at
 least a couple of our
 power users are very happy with this solution, as it provides
 first-class access to utilities relevant to maintaining the ACL2
 system and books (like GNU Make and perl).</li>

 <li>Set up <a
 href='https://en.wikipedia.org/wiki/Windows_Subsystem_for_Linux'>Windows
 Subsystem for Linux</a> (WSL) on a 64-bit version of Windows 10 (or later,
 once available).  Within that subsystem, follow the normal @(see
 installation-instructions) for ACL2. See the below section regarding the ACL2
 Sedan Windows installation instructions for more info, as that involves
 installing the ACL2 Sedan in WSL on Windows.</li>

 <li>Use the ACL2 Sedan (ACL2s) Windows installation instructions &mdash; see
 @(see acl2s::acl2s-installation) for more details. This will install ACL2 and
 the ACL2s system (including a copy of the Eclipse IDE with ACL2s support) in a
 Windows Subsystem for Linux distro. This distro is configured to automatically
 open Eclipse when the distro starts up, but one can start the distro without
 Eclipse by running @('wsl -d acl2s -e /bin/bash --noprofile').</li>

 </ul>

 <p>You are welcome to <a
 href='http://www.cs.utexas.edu/users/moore/acl2/v3-6/distrib/windows/'>obtain
 a Windows installer for a previous ACL2 release</a>, which mimics some of
 Linux and provides Emacs.  Updated ACL2 binaries have been successfully
 installed in such an environment.</p>

 <p>When installing ACL2 on Windows without a
 Unix-like environment, consider at least downloading a utility such as
 @('djtarnt.exe') to use with the @('-x') option on gzipped tarfiles.</p>

 <p>Gnu tar is preferred, as there have been some problems
 with long file names when using at least one other tar program.  You may want
 to use the @('-i') option, @('tar xpvfi ...'), if you have problems with
 other than Gnu tar.  You can see if you have Gnu tar by running @('tar -v').
 </p>

 <p>WARNING:
 At least one user experienced CR/LF issues when using WinZIP, but we have
 received the suggestion that people untarring with that utility should
 probably turn off smart cr/lf conversion.</p>

 <p>Here are links to some older documentation topics, possibly out of date,
 that provide additional information for installing ACL2 on Windows.</p>

 <ul>

 <li>See @(see windows-installation-gcl) for building an executable image on a
 Windows system using GCL</li>

 <li>Click <a
 href='https://www.cs.utexas.edu/users/moore/acl2/contrib/windows7.html'>here</a>
 for some older instructions for building ACL2 on Windows.</li>

 <li>Click <a
 href='https://www.cs.utexas.edu/users/moore/acl2/contrib/windows-gcl-jared.html'>here</a>
 for yet older instructions for building ACL2 on Windows using mingw.</li>

 </ul>")
other
(defxdoc windows-installation-gcl
  :parents (windows-installation)
  :short "Building an executable image on a Windows system using GCL"
  :long "<p>This topic is based on very old documentation that is probably
 superseded by the topic, @(see windows-installation).  But here are steps that
 <i>may</i> be helpful when installing ACL2 on Windows with GCL as the host
 Common Lisp.</p>

 <ol>

 <li><b>FIRST</b> get GCL running on your Windows system using <b>ONE</b> of the
 following two options.  Note that GCL can be unhappy with spaces in filenames,
 so you should probably save the GCL distribution to a directory whose path is
 free of spaces.

 <ul>

 <li><a href='https://www.gnu.org/software/gcl/'>Obtain GCL for Windows
 systems</a> if such a distribution is available.</li>

 <li><b>OR</b>, perhaps you can build GCL on your Windows system from the
 sources.  The mingw tools and the cygnus bash shell have been used to build
 distributed GCL executables.</li>

 </ul></li>

 <li><b>SECOND</b>, create an appropriate GCL batch file.  When we tried
 running the script @('gclm/bin/gclm.bat'), a separate window popped up, and
 with an error.  Many ACL2 users prefer running in an emacs shell buffer.  The
 following modification of @('gclm.bat') seemed to solve the problem
 (your pathnames may vary).

 @({
 @
 % do not delete this line %
 @ECHO off
 set cwd=%cd%
 path C:\gcl\gclm\mingw\bin;%PATH%
 C:\gcl\gclm\lib\gcl-2.6.2\unixport\saved_gcl.exe -dir C:/gcl/gclm/lib/gcl-2.6.2/unixport/ -libdir  C:/gcl/gclm/lib/gcl-2.6.2/ -eval "(setq si::*allow-gzipped-file* t)" %1 %2 %3 %4 %5 %6 %7 %8 %9
 })</li>

 <li><b>THIRD</b>, see @(see creating-executable), and follow the instructions
 in the section, &ldquo;Building an executable image on other than a Unix-like
 system&rdquo;.  The resulting file may be called @('saved_acl2.exe') rather
 than @('saved_acl2').</li>

 <li><b>FINALLY</b>, create a suitable file @('acl2.bat').</li>

 </ol>

 <p>If you experience problems, the following hints may help.</p>

 <h3>TROUBLESHOOTING</h3>

 <ul>

 <li>In an attempt to build ACL2 on Windows XP on top of GCL, the attempt broke
 at the end of the &ldquo;Initialization, first pass&rdquo; step (see @(see
 creating-executable)), while compiling @('TMP1.lisp').  That was easily
 remedied by starting up a fresh GCL session and invoking @('(compile-file
 "TMP1.lisp")') before proceeding to the next step.</li>

 <li>When you want to quit ACL2, invoke @('(good-bye)').  The point here is to
 avoid @('control-c control-d'), even though that often works fine in Emacs
 under Unix-like systems.</li>

 <li>If the above batch file does not work for some reason, an alternate
 approach may be to set environment variables.  You may be able to add to the
 @('PATH') variable <i>gcl-dir</i>@('\gcc\bin'), where <i>gcl-dir</i> is the
 directory where GCL is installed.  To get to the place to set environment
 variables, you might be able to go to the control panel, under system, under
 advanced.  Alternately, you might be able to get there by opening @('My
 Computer') and right-clicking to get to @('Properties'), then selecting the
 @('Advanced') tab.  At one time, when GCL/Windows was released as Maxima, Pete
 Manolios once suggested adding the system variable @('LD_LIBRARY_PATH') with
 the value @('"maxima-dir\gcc\i386-mingw32msvc\include"'); this may or may
 not be necessary for your GCL installation (and the path would of course
 likely be different).</li>

 </ul>")
other
(defxdoc with-brr-data
  :parents (debugging break-rewrite)
  :short "Finding the source of a term in prover output"
  :long "<p>When a proof attempt fails, a good first step is typically to look
 at <i>checkpoints</i>; see @(see the-method).  That step is often sufficient.
 But occasionally a checkpoint contains an undesirable term whose source is a
 mystery, and it may be useful to find the origin of that term.
 @('With-brr-data') is a utility that collects such data that can be queried by
 various utilities, for example as follows.</p>

 @({
 Example:

 ; Collect brr-data when attempting the indicated proof:
 (with-brr-data (thm (equal (append x y) (append y x))))

 ; Show a path leading to a rewrite result that contains
 ; (append y (cdr x)) as a subterm:
 (cw-gstack-for-subterm (append y (cdr x)))

 ; Same as above, except enter a loop to query for additional such results:
 (cw-gstack-for-subterm* (append y (cdr x)))
 })

 <p>The rest of this documentation topic is structured as follows.  It may
 suffice to read only the first two sections.</p>

 <ul>

 <li>Introduction</li>

 <li>Connections with @(see break-rewrite)</li>

 <li>General form of @('with-brr-data') calls</li>

 <li>General forms of queries</li>

 <li>Keyword arguments of @('with-brr-data') (optional)</li>

 <li>Low-level details (optional)</li>

 <li>Using attachments to modify functionality of @('with-brr-data')</li>

 </ul>

 <h3>Introduction</h3>

 <p>@('(With-brr-data form)') evaluates @('form') while collecting data on rule
 application &mdash; often @(see rewrite) and @(see definition) rules, but also
 @(see linear) and @(see rewrite-quoted-constant) rules.  Query utilities allow
 one to search the collected data for a specified result of a rule application
 and print a stack of operations leading to that result.  The name
 &ldquo;brr&rdquo; is suggestive of the @(see break-rewrite) utility, which
 shares some aspects with the @('with-brr-data') utility: in particular, the
 @(':path+') command of break-rewrite shows a stack of operations in the same
 way as the query utilities for @('with-brr-data').  The next section,
 &ldquo;Connection with @(see break-rewrite)&rdquo;, further explores the
 relationship between break-rewrite and @('with-brr-data').</p>

 <p>The collection of break-rewrite data can slow down the theorem prover, but
 the slowdown will probably be modest, perhaps adding an extra 15% or so to the
 time.</p>

 <p>We turn now to examples that illustrate how @('with-brr-data') works with
 associated query utilities.  These examples are intended to make it clear how
 to use these utilities, but further information is provided in later sections
 for those who are interested.  Note that each of these examples attempts to
 prove a non-theorem; they are chosen simply to illustrate tool usage.</p>

 <h4>Example Set 1</h4>

 <p>Our first illustration of @('with-brr-data') and associated query utilities
 uses the following (non-theorem) example, mentioned earlier.</p>

 @({
 (with-brr-data (thm (equal (append x y) (append y x))))
 })

 <p>ACL2 produces the following checkpoints, exactly as though the @(tsee thm)
 call were evaluated without the surrounding call of @('with-brr-data').
 (The optional section on &ldquo;Low-level details&rdquo; discusses the
 &ldquo;ACL2 Observation:&rdquo; printed at the end by @('with-brr-data').)</p>

 @({
 *** Key checkpoint at the top level: ***

 Goal
 (EQUAL (APPEND X Y) (APPEND Y X))

 *** Key checkpoints under a top-level induction
     before generating a goal of NIL (see :DOC nil-goal): ***

 Subgoal *1/2''
 (IMPLIES (AND (CONSP X)
               (EQUAL (APPEND (CDR X) Y)
                      (APPEND Y (CDR X))))
          (EQUAL (CONS (CAR X) (APPEND Y (CDR X)))
                 (APPEND Y X)))

 Subgoal *1/1''
 (IMPLIES (NOT (CONSP X))
          (EQUAL Y (APPEND Y X)))

 ACL2 Error [Failure] in ( THM ...):  See :DOC failure.

 ******** FAILED ********

 ACL2 Observation:  (LENGTH (@ BRR-DATA-LST)) = 16
 ACL2 !>
 })

 <p>Consider the term @('(APPEND Y (CDR X))') occurring in one of these
 checkpoints.  It might not be clear, at least at first glance, how this term
 came about during the proof.  We can find at least one source of that term by
 issuing the @('cw-gstack-for-subterm') query shown below, which searches
 &ldquo;top-level&rdquo; rewrites &mdash; those not invoked when relieving
 hypotheses of rules &mdash; for a result that contains the given term, in this
 case @('(append y (cdr x))'), as a subterm.  The output is similar to the
 output of the utility, @(tsee cw-gstack), followed by the result of the
 bottom-most rewriter call, which contains the given term as a subterm.  (See
 @(see term) for discussion of &ldquo;translated&rdquo; and
 &ldquo;untranslated&rdquo; terms.)</p>

 @({
 ACL2 !>(cw-gstack-for-subterm (append y (cdr x)))
 1. Simplifying the clause
      ((NOT (CONSP X))
       (NOT (EQUAL (BINARY-APPEND (CDR X) Y)
                   (BINARY-APPEND Y (CDR X))))
       (EQUAL (BINARY-APPEND X Y)
              (BINARY-APPEND Y X)))
 2. Rewriting (to simplify) the atom of the third literal,
      (EQUAL (BINARY-APPEND X Y)
             (BINARY-APPEND Y X)),
 3. Rewriting (to simplify) the first argument,
      (BINARY-APPEND X Y),
 4. Attempting to apply (:DEFINITION BINARY-APPEND) to
      (BINARY-APPEND X Y)
 The resulting (translated) term is
   (CONS (CAR X)
         (BINARY-APPEND Y (CDR X))).
 ACL2 !>
 })

 <p>One might realize that @('(BINARY-APPEND Y (CDR X))') comes about from
 expanding @('(BINARY-APPEND X Y)') to expose the term @('(BINARY-APPEND (CDR
 X) Y)') and then using the inductive hypothesis to swap the arguments.  In
 that case, the mystery of the term's appearance is solved!  But if that isn't
 clear, one at least has the clue from Frame 4 above that the term is produced
 by applying the definition of @(tsee binary-append).  With that information
 one can issue a @(tsee monitor!) command as follows.</p>

 @({
 :monitor! (:definition binary-append)
           (equal (brr@ :target) '(binary-append x y))
 })

 <p>We now issue the @(tsee thm) call above, with or without the wrapper of
 @('with-brr-data').  After breaking twice (see @(see break-rewrite)) and
 proceeding with @(':go') to find two failed attempts to use the definition of
 @('binary-append'), we explore at the third break as follows.</p>

 @({
 1 ACL2 >:type-alist

 Decoded type-alist:
 -----
 Terms with type *TS-T*:
 (EQUAL (APPEND (CDR X) Y)
        (APPEND Y (CDR X)))
 -----
 Terms with type *TS-CONS*:
 X

 ==========
 Use (GET-BRR-LOCAL 'TYPE-ALIST STATE) to see actual type-alist.
 1 ACL2 >:target
 (BINARY-APPEND X Y)
 1 ACL2 >:eval

 1! (:DEFINITION BINARY-APPEND) produced
 (CONS (CAR X) (BINARY-APPEND Y (CDR X))).

 1 ACL2 >
 })

 <p>The log above shows how the term @('(BINARY-APPEND Y (CDR X))') was
 produced: the definition of @('binary-append') was expanded on the term
 @('(BINARY-APPEND X Y)'), and the inductive hypothesis &mdash; represented in
 the @(':type-alist') command's output &mdash; is applied to swap the resulting
 arguments.</p>

 <p>We can find more sources of the same term by using the &ldquo;@('*')&rdquo;
 version of the @('cw-gstack-for-subterm') command as follows.  By repeatedly
 responding with &ldquo;@('y')&rdquo; to the query presented by the system, we
 find three additional paths leading to the desired subterm.</p>

 @({
 (cw-gstack-for-subterm* (append y (cdr x)))
 })

 <p>While @('cw-gstack-for-subterm') and @('cw-gstack-for-subterm*') may be the
 most useful queries in general, one may wish to search for paths leading to
 <i>exactly</i> a given term rather than paths to a term <i>containing</i> that
 term (as above).  The queries @('cw-gstack-for-term') and
 @('cw-gstack-for-term*') may be used for this purpose, for example as
 follows.</p>

 @({
 (cw-gstack-for-term (append y (cdr x)))
 (cw-gstack-for-term* (append y (cdr x)))
 })

 <p>Finally, these queries support searching for <i>instances</i> of a term or
 subterm, by supplying a &ldquo;term&rdquo; of the form @('(:free (v1 ... vn)
 u)') where @('v1') through @('vn') are distinct variables and @('u') is a
 term.  Each of the following produces the path shown above.</p>

 @({
 (cw-gstack-for-term (:free (u v) (cons u v)))
 (cw-gstack-for-term* (:free (u v) (cons u v)))
 })

 <p>Notice that the use of this @(':free') construct allows one to search for
 the source of a call of any function symbol @('f'), as with @('cons') above.
 If @('f') has k formals, then one can supply the argument @('(:free (x1
 ... xk) (f x1 ... xk))') to find a rewriter call that produces a call of
 @('f').</p>

 <h4>Example Set 2</h4>

 <p>Consider the following (admittedly contrived) example.</p>

 @({
 (defstub f0 (x) t)

 (defun f1 (x)
   (cons x x))

 (defun f2 (x)
   (f1 (f0 x)))

 (defun f3 (x)
   (if (atom x)
       (f2 x)
     (f2 (car x))))

 (with-brr-data
  (thm (equal (f3 x)
              yyy)))
 })

 <p>The call of @(tsee thm) produces the following checkpoint.</p>

 @({
 (IMPLIES (CONSP X)
          (EQUAL (CONS (F0 (CAR X)) (F0 (CAR X)))
                 YYY))
 })

 <p>In this simple example it's easy to figure out how the term @('(F0 (CAR
 X))') was produced.  But suppose we were surprised to see that term.  We might
 issue the following query but be disappointed in the result.</p>

 @({
 ACL2 !>(cw-gstack-for-term (F0 (CAR X)))
 There are no results.
 ACL2 !>
 })

 <p>To see why there are no results, recall that @('with-brr-data') collects
 data from rule applications.  However, no rule produced the term @('(F0 (CAR
 X))').  This becomes clear if we issue a query that looks for that term as a
 subterm of a rule application's result.</p>

 @({
 ACL2 !>(cw-gstack-for-subterm (F0 (CAR X)))
 1. Simplifying the clause
      ((EQUAL (F3 X) YYY))
 2. Rewriting (to simplify) the atom of the first literal,
      (EQUAL (F3 X) YYY),
 3. Rewriting (to simplify) the first argument,
      (F3 X),
 4. Attempting to apply (:DEFINITION F3) to
      (F3 X)
 5. Rewriting (to simplify) the body,
      (IF (CONSP X) (F2 (CAR X)) (F2 X)),
    under the substitution
      X : X
 6. Rewriting (to simplify) the second argument,
      (F2 (CAR X)),
    under the substitution
      X : X
 7. Attempting to apply (:DEFINITION F2) to
      (F2 (CAR X))
 8. Rewriting (to simplify) the rhs of the conclusion,
      (F1 (F0 X)),
    under the substitution
      X : (CAR X)
 9. Attempting to apply (:DEFINITION F1) to
      (F1 (F0 (CAR X)))
 The resulting (translated) term is
   (CONS (F0 (CAR X)) (F0 (CAR X))).
 Note: The first lemma application above that provides a suitable result
 is at frame 4, and that result is
   (IF (CONSP X)
       (CONS (F0 (CAR X)) (F0 (CAR X)))
     (CONS (F0 X) (F0 X))).
 ACL2 !>
 })

 <p>We see that the term @('(FO (CAR X))') is not itself the result of a rule
 application.  This example illustrates that one may often get better results
 using @('cw-gstack-for-subterm') rather than @('cw-gstack-for-term').</p>

 <p>It is also interesting to look at the &ldquo;Note&rdquo; printed at the
 end.  The query utilities search for the first rule application that produced
 a suitable result, and then they search from that point for a maximally deeper
 rule application that produced a suitable result.  In this case, the first
 rule that produced a term containing @('(FO (CAR X))') is shown in the frame
 at position 4, as per the Note.  The rule at frame 9 also produced such a
 term (though a different one than at frame 4), and there was no deeper such
 rule application &mdash; that is, from the time the definition at frame 9 was
 applied till the time its body was fully rewritten, no rule produced a term
 containing @('(FO (CAR X))').  (This notion of &ldquo;deeper&rdquo; is
 discussed at some length in the section below on &ldquo;General forms of
 queries&rdquo;.)</p>

 <p>Next we'll explore a limitation of these tools and how to get around
 it.  We start as follows (following the definitions above).</p>

 @({
 (with-brr-data
  (thm (equal (append (f3 x) y)
              z)
       :hints (("Goal" :in-theory (disable append)))))
 })

 <p>This proof attempt results in the following checkpoint.</p>

 @({
 (IMPLIES (CONSP X)
          (EQUAL (APPEND (CONS (F0 (CAR X)) (F0 (CAR X)))
                         Y)
                 Z))
 })

 <p>The following log may be surprising, especially since the indicated term
 need only be a subterm of a rewriter result, and we see this exact term in the
 checkpoint above!</p>

 @({
 ACL2 !>(cw-gstack-for-subterm (APPEND (CONS (F0 (CAR X)) (F0 (CAR X))) Y))
 There are no results.
 ACL2 !>
 })

 <p>A solution is to choose a subterm of that input term, as shown in the log
 below.  The resulting output shows why the query above yielded no results:
 frame 6 below shows that the first argument, @('(F3 X)'), of
 @('binary-append') (see frame 3 below) generates a call of @('IF'), so the
 rewrite at frame 3 will generate a term of the form @('(BINARY-APPEND (IF ...)
 ...)'), not of the form @('(BINARY-APPEND (CONS ...) ...)').</p>

 @({
 ACL2 !>(cw-gstack-for-subterm (cons (f0 (car x)) (f0 (car x))))
 1. Simplifying the clause
      ((EQUAL (BINARY-APPEND (F3 X) Y) Z))
 2. Rewriting (to simplify) the atom of the first literal,
      (EQUAL (BINARY-APPEND (F3 X) Y) Z),
 3. Rewriting (to simplify) the first argument,
      (BINARY-APPEND (F3 X) Y),
 4. Rewriting (to simplify) the first argument,
      (F3 X),
 5. Attempting to apply (:DEFINITION F3) to
      (F3 X)
 6. Rewriting (to simplify) the body,
      (IF (CONSP X) (F2 (CAR X)) (F2 X)),
    under the substitution
      X : X
 7. Rewriting (to simplify) the second argument,
      (F2 (CAR X)),
    under the substitution
      X : X
 8. Attempting to apply (:DEFINITION F2) to
      (F2 (CAR X))
 9. Rewriting (to simplify) the rhs of the conclusion,
      (F1 (F0 X)),
    under the substitution
      X : (CAR X)
 10. Attempting to apply (:DEFINITION F1) to
      (F1 (F0 (CAR X)))
 The resulting (translated) term is
   (CONS (F0 (CAR X)) (F0 (CAR X))).
 Note: The first lemma application above that provides a suitable result
 is at frame 5, and that result is
   (IF (CONSP X)
       (CONS (F0 (CAR X)) (F0 (CAR X)))
     (CONS (F0 X) (F0 X))).
 ACL2 !>
 })

 <p>The careful reader may notice another reason that the @('append') call does
 not yield a match: no such call is the result of a rewriter call.</p>

 <p>The moral of this story is that if a term fails to give you a match, then
 use a subterm of it.  You can also use the @(':free') construct mentioned
 above, for example as follows &mdash; this gives the same output as shown in
 the log just above.</p>

 @({
 (cw-gstack-for-subterm (:free (v) (cons (f0 v) (f0 v))))
 })

 <h3>Connections with break-rewrite</h3>

 <p>We noted above that after running @('with-brr-data'), the stacks (paths)
 displayed by query commands such as @('cw-gstack-for-term') are the same as
 the stacks displayed by the @(see break-rewrite) command, @(':path+').</p>

 <p>But there are these additional connections between @('with-brr-data') and
 the break-rewrite utility.</p>

 <ul>

 <li>The same rewriting processes are considered by @('with-brr-data') as by
 break-rewrite; in particular, abbreviation rules are not considered during
 preprocessing (see @(see monitor)).</li>

 <li>When a query command (@('cw-gstack-for-term') etc.) finds a match with a
 rewriting result, it discards the result if the input &mdash; the
 @(':target'), in the parlance of @(see break-rewrite) &mdash; contains that
 match.</li>

 <li>@(csee Monitor)ed @(see rune)s are indeed monitored during evaluation of a
 call of @('with-brr-data'), even if break-rewrite has not been enabled
 globally (using @(':')@(tsee brr) or @(tsee monitor!)).  If this is not
 desired, then @(see unmonitor) runes before calling @('with-brr-data').</li>

 <li>There is the following low-level way to collect brr-data for queries such
 as @('cw-gstack-for-term') without calling @('with-brr-data'): @('(assign
 gstack :brr-data)').  But you may want to clear such data afterwards, which
 you can do by evaluating the form, @('(clear-brr-data-lst)').  Otherwise the
 brr-data from later proof attempts will be combined, probably in unexpected
 ways, with brr-data from earlier proof attempts.</li>

 <li>@('With-brr-data') and its queries pay no attention to
 &ldquo;near-miss&rdquo; breaks (see @(see break-rewrite) for discussion of
 these breaks).</li>

 </ul>

 <p>The first item above is worth emphasizing.  Consider the following
 example.</p>

 @({
 (include-book "std/lists/rev" :dir :system)
 (with-brr-data
  (thm (implies (and (natp n)
                     (< n (len x)))
                (equal (nth n (revappend x y))
                       (nth n (reverse x))))
       :hints (("Goal" :do-not '(preprocess)))))
 (cw-gstack-for-subterm (APPEND (REV X) Y))
 })

 <p>The @('cw-gstack-for-subterm') query yields a result in this example, but
 not if we change it to remove the @(':')@(tsee hints).  If we use @(':')@(tsee
 pso) on the proof attempt without the @(':hints'), we notice that the
 requested subterm was introduced by &ldquo;the simple :rewrite rule
 REVAPPEND-REMOVAL&rdquo;; here &ldquo;simple&rdquo; indicates the use of the
 <i>preprocess</i> process for simplification, which avoids the usual rewriter.
 If we instead query the no-hints version with @('(cw-gstack-for-subterm (REV
 X))'), the output below shows that a chain of rewrites generates
 @('(APPEND (REV X) Y)') as an intermediate term but not as the result of a
 rewrite.</p>

 @({
 ACL2 !>(cw-gstack-for-subterm (REV X))
 1. Simplifying the clause
      ((NOT (INTEGERP N))
       (< N '0)
       (NOT (< N (LEN X)))
       (EQUAL (NTH N (BINARY-APPEND (REV X) Y))
              (NTH N (REVERSE X))))
 2. Rewriting (to simplify) the atom of the fourth literal,
      (EQUAL (NTH N (BINARY-APPEND (REV X) Y))
             (NTH N (REVERSE X))),
 3. Rewriting (to simplify) the second argument,
      (NTH N (REVERSE X)),
 4. Rewriting (to simplify) the second argument,
      (REVERSE X),
 5. Attempting to apply (:DEFINITION REVERSE) to
      (REVERSE X)
 6. Rewriting (to simplify) the body,
      (IF (STRINGP X)
          (COERCE (REVAPPEND (COERCE X 'LIST) 'NIL)
                  'STRING)
        (REVAPPEND X 'NIL)),
    under the substitution
      X : X
 7. Rewriting (to simplify) the third argument,
      (REVAPPEND X 'NIL),
    under the substitution
      X : X
 8. Attempting to apply (:REWRITE REVAPPEND-REMOVAL) to
      (REVAPPEND X 'NIL)
 9. Rewriting (to simplify) the rhs of the conclusion,
      (BINARY-APPEND (REV X) Y),
    under the substitution
      Y : 'NIL
      X : X
 10. Attempting to apply (:REWRITE APPEND-ATOM-UNDER-LIST-EQUIV) to
      (BINARY-APPEND (REV X) 'NIL)
 The resulting (translated) term is
   (REV X).
 Note: The first lemma application above that provides a suitable result
 is at frame 5, and that result is
   (IF (STRINGP X)
       (COERCE (REV (COERCE X 'LIST)) 'STRING)
     (REV X)).
 ACL2 !>
 })

 <p>The version of this example without @(':hints') also illustrates the second
 item above, about discarding matches that occur in the @(':target') of
 rewriting.  Without that restriction we would see a result for the query
 @('(cw-gstack-for-subterm (APPEND (REV X) Y))') from an attempt to rewrite the
 term @('(NTH N (APPEND (REV X) Y))').  But that would not help us to find the
 source of the term @('(APPEND (REV X) Y)').</p>

 <h3>General form of @('with-brr-data') calls</h3>

 <p>The general form, including optional keyword arguments, is</p>

 @({
 (with-brr-data form :global-var var :brr-data-returned bool)
 })

 <p>where @('form') is typically an event but is only required to evaluate to
 an @(see error-triple).  By default (i.e., when the keyword arguments are
 omitted), that error triple is returned by the @('with-brr-data') call.</p>

 <p>There is probably little reason for most users to supply either keyword
 argument.  They are documented in the section after next.</p>

 <p><b>Notes</b>.</p>

 <ul>

 <li>The data collected by a call of <tt>with-brr-data</tt> will persist until
 the next call of @('with-brr-data').</li>

 <li>Behavior is undefined for nested calls of @('with-brr-data').  (If this
 presents a problem then you may ask the ACL2 implementors to consider
 specifying that behavior.)</li>

 </ul>

 <h3>General forms of queries</h3>

 <p>The four queries (all illustrated above) are as follows, where the keyword
 argument is optional.</p>

 @({
 (cw-gstack-for-subterm u :global-var var)
 (cw-gstack-for-subterm* u :global-var var)
 (cw-gstack-for-term u :global-var var)
 (cw-gstack-for-term* u :global-var var)
 })

 <p>In each case, @('u') is either a term (which can be a user-level term,
 i.e., not necessarily translated; see @(see term)) or of the form @('(:free
 (v1 ... vk) u1)') where @('u1') is a term.  In the latter case, @('v1')
 through @('vk') must be distinct variables that all occur in (the translation
 of) @('u1').</p>

 <p>These queries are effective after data collection using @('with-brr-data'),
 which is typically wrapped around an event that calls the theorem prover.  To
 understand how the queries work, it is useful to view a proof attempt as
 generating &ldquo;initial&rdquo; calls of the rewriter, such as when rewriting
 a hypothesis or the conclusion of a goal (technically, a literal of the goal
 clause; see @(see clause)): that is, initial rewriter calls are those that are
 not under another rewriter call.  Then data collection under each initial call
 creates a tree of &ldquo;top-level&rdquo; calls &mdash; those not made under
 an attempt to relieve a hypothesis &mdash; for which that initial call is the
 root.  Thus each node of that tree corresponds to a rewriter call, and each
 child of that node is a top-level call of the rewriter that is immediately
 under that call, where the order of calls is respected by the ordering of
 child nodes from left to right.  For example, the top-level application a
 rewrite rule corresponds to a node, and the call to rewrite the right-hand
 side of the rule (with appropriate variable bindings) corresponds to a child
 of that node.  Another example is when an attempt to rewrite a function call
 leads to an attempt to rewrite an argument of that call: the latter
 corresponds to a child node of the former.  Each of the four query utilities
 looks for the first root node, and the left-most branch under that node, that
 results in a rewriter result that &ldquo;matches&rdquo; the input in the
 following sense.</p>

 <p>This notion of &ldquo;matches&rdquo; depends on the call, as follows.
 First assume that the input is a term.  For @('cw-gstack-for-subterm') and
 @('cw-gstack-for-subterm*'), the result matches when it contains the given
 term as a subterm.  For @('cw-gstack-for-term') and @('cw-gstack-for-term*'),
 the result matches when it is exactly the given term.  Now suppose the input
 is @('(:free (v1 ... vk) u)').  Then the notion of &ldquo;matches&rdquo; is
 modified to allow any instance @('u/s') for a substitution @('s') that
 instantiates only the variables @('vi').</p>

 <p>When a matching node @('N1') is found for the input term, or in the case of
 @('(:free (v1 ... vk) u)'), some instance of @('u'), then a further search
 below @('N') is made to find a maximal left-most branch below it that
 terminates in a node @('N2') that also matches, using the same substitution in
 the case of @(':free').  If no such branch is found, then @('N2') is @('N').
 Either way, the term or instance that matched at @('N') (as a subterm in the
 case of @('cw-gstack-for-subterm') or @('cw-gstack-for-subterm*'), else as an
 exact match) also matches at @('N2').  The output then shows a path to
 @('N2'), but if @('N1') and @('N2') differ then the output also notes that the
 first match was at @('N1'), as we have seen in each &ldquo;Note&rdquo; at the
 end of logs displayed above.</p>

 <p>The discussion above characterizes the behavior of
 @('cw-gstack-for-subterm') and @('cw-gstack-for-term'); now let us consider
 @('cw-gstack-for-subterm*') and @('cw-gstack-for-term*').  These
 &ldquo;@('*')&rdquo; versions query after each result to ask if another result
 is desired.  If so, the search starts strictly after @('N'); it does not look
 for a second successor @('N2') of @('N').  The search continues until either
 the user answers @('n') (regardless of the package; the query cares only that
 the @(tsee symbol-name) is @('"Y"') or @('"N"')) or there are no more
 results.</p>

 <h3>Keyword arguments of @('with-brr-data') (optional)</h3>

 <p>As noted above, the general form of a call of @('with-brr-data') is as
 follows.</p>

 @({
 (with-brr-data form :global-var var :brr-data-returned bool)
 })

 <p>The keywords have aspects that are quite technical, so unless you are
 somewhat familiar with ACL2 implementation issues you will probably want to
 skip this section.</p>

 <p>Neither keyword argument is evaluated.  The behavior of the keyword
 arguments depends on a list, @('BDL') (&ldquo;Brr-Data List&rdquo;), that is
 typically made available by a call of @('with-brr-data'), as described below.
 The members of @('BDL') represent successful initial calls of the rewriter, in
 order.  Each of those members is a @('brr-data') record, as described in the
 next section.  After the @('with-brr-data') call returns, then @('(mv nil BDL
 state)') is returned by evaluation of @('(brr-data-lst state)'), until the
 next time that either a call of @('with-brr-data') or the form
 @('(clear-brr-data-lst)') is evaluated.  Implementation notes: information is
 stored in the @('brr-data') @(see wormhole); @('(brr-data-lst state)')
 extracts that information and reorders appropriately before producing
 @('BDL'); and @('(clear-brr-data-lst)') removes that information from the
 @('brr-data') wormhole.</p>

 <p>We now explain the keyword arguments in terms of the list @('BDL').</p>

 <ul>

 <li>@(':global-var var')<br/>

 The symbol @('var') defaults to the symbol, @('brr-data-lst').  @('Var') is
 either @('nil') or a state global variable (see @(see
 programming-with-state)), which by default is @('brr-data-lst').  If @('var')
 is not @('nil'), then the @('with-brr-data') call modifies @(see state) by
 setting the value of the state global, @('var'), to @('BDL').</li>

 <li>@(':brr-data-returned bool')<br/>

 Suppose that the @('form') argument of the @('with-brr-data') call evaluates
 to @('(mv erp val state)').  Then when @('bool') is @('nil') (which is the
 default), the @('with-brr-data') call returns that same @(see error-triple),
 @('(mv erp val state)').  If however @('bool') is not @('nil'), then instead
 the @('with-brr-data') call returns @('(mv erp BDL state)').</li>

 </ul>

 <h3>Low-level details (optional)</h3>

 <p>This implementation-level section further describes the @('brr-data')
 structure mentioned above.  It is probably of interest only to those who
 consider writing their own tools to query the data produced by
 @('with-brr-data').</p>

 <p>A @('brr-data') record is a structure that has a field @(':brr-data-1')
 representing information from entry into the rewriter, a field
 @(':brr-data-2') representing information from the corresponding exit from the
 rewriter, and a field @(':completed') that is the list of @('brr-data')
 records produced between that entry and exit, in order.  (Implementation
 detail: these are produced inside the @('brr-data') @(see wormhole) by the
 same functions, @('brkpt1') and @('brkpt2'), that implement the @(see
 break-rewrite) utility.)</p>

 @({
 (defrec brr-data
   (pre post . completed)
   nil)

 (defrec brr-data-1
   (((lemma . target) . (unify-subst type-alist . geneqv))
    .
    ((pot-list . ancestors) . (rcnst initial-ttree . gstack)))
   nil)

 (defrec brr-data-2
   ((failure-reason unify-subst . brr-result)
    .
    (rcnst final-ttree . gstack))
   nil)
 })

 <p>The @('brr-data') definition introduces a recursive data type (as per ACL2
 source function @('brr-data-p'), since the @(':completed') field is a list of
 @('brr-data') records.  These correspond to immediate sub-calls of the
 rewriter, yielding &ldquo;child nodes&rdquo; as described in the section,
 &ldquo;General forms of queries&rdquo;.</p>

 <p>We have seen above that the use of @('with-brr-data') activates the
 collection of break-rewrite data.  Collection may also be activated by
 assigning the @(see state) global, @('gstackp'), to the value @(':brr-data').
 (See @(see programming-with-state) for relevant programming background.)  You
 can use @(':')@(tsee trans1) on a @('with-brr-data') call to see how
 @('with-brr-data') sets @('gstackp').  Note that setting (or binding)
 @('gstackp') to @(':brr-data') has the effect of @(':')@(tsee brr)@(' t') but
 enhanced with collection of @('brr-data') records.  When @('gstackp') has
 value @(':brr-data'), @(':brr t') is treated as a no-op and @(':brr nil') is
 an error, to avoid inadvertently turning off @('brr-data') record collection.
 Note that although @('with-brr-data') is disallowed in ACL2(p) (see @(see
 parallelism)) when @(see waterfall-parallelism) is enabled, this prohibition
 can be circumvented by assigning @('gstackp') to @(':brr-data'); however, in
 that case @('with-brr-data') might well not behave correctly.</p>

 <p>The programmer who manipulates @('brr-data') records may wish to look at
 the ACL2 source code and the @(see break-rewrite) documentation to understand
 the fields of the @('brr-data-1') and @('brr-data-2') records.  The form
 @('(brr-data-listp t lst)') recognizes a list of well-formed @('brr-data')
 records.  The @(':failure-reason') field of the @('brr-data-2') record may be
 of particular interest; see ACL2 source function
 @('tilde-@-failure-reason-phrase1') for the forms that this field may
 take.</p>

 <p>It is easy to see the list of @('brr-data') records created by a call of
 @('with-brr-data').  A big hint is given in the output printed at the
 completion of a @('with-brr-data') call, as suggested in the first example in
 the introduction, with the following output.</p>

 @({
 ACL2 Observation:  (LENGTH (@ BRR-DATA-LST)) = 16
 })

 <p>The form @('(@ BRR-DATA-LST)') evaluates to the resulting list of
 @('brr-data') records, one for each so-called &ldquo;initial call&rdquo; of
 the rewriter, in the sense described in the section above on &ldquo;Keyword
 arguments&rdquo;.  The utility @('show-brr-data-lst') can be applied to such a
 list to show the most interesting parts of each record, for example,
 @('(show-brr-data-lst (@ brr-data-lst))').  Also you can call the utility
 @('show-brr-data') on a single @('brr-data') record.</p>

 <h3>Using attachments to modify functionality of @('with-brr-data')</h3>

 <p>The behavior of @('with-brr-data') is customizable by using attachments
 (see @(see defattach)).  The macro, @('set-brr-data-attachments'), has been
 provided for this purpose.  This section provides only minimal documentation
 on this customizability; those who want to implement new such attachments can
 look at the following examples in the @(see community-books) to get a sense of
 how that might be done.  Note that the query utilities work the same
 regardless of the attachments, and the relevant data structures are also
 unchanged.</p>

 @({
 books/kestrel/utilities/brr-data-all.lisp
 books/kestrel/utilities/brr-data-failures.lisp
 })

 <p>When the macro is called with no arguments, i.e.,
 @('(set-brr-data-attachments)'), behavior is restored to the built-in behavior
 as described above.  But this macro can be given an argument that indicates a
 string: it is either a string or a symbol, where a symbol indicates its @(tsee
 symbol-name).  The indicated string, which we write below as @('"<S>"'), is
 added as a suffix after a hyphen to create four system attachments.  These are
 @(tsee defattach) calls rather than @(tsee defattach-system) calls, so that
 their effect is not @(see local) to the enclosing book.</p>

 @({
 (defattach (brkpt1-brr-data-entry brkpt1-brr-data-entry-<S> :system-ok t)
 (defattach (brkpt2-brr-data-entry brkpt2-brr-data-entry-<S> :system-ok t)
 (defattach (update-brr-data-1 update-brr-data-1-<S>) :system-ok t)
 (defattach (update-brr-data-2 update-brr-data-2-<S>) :system-ok t)
 })

 <p>The four @('"-<S>"') functions must be defined to match the signatures of
 the functions to which they are attached.  Those functions have the following
 arguments and results, where @('*') indicates an ordinary (non-@(see stobj))
 value.</p>

 @({
 (brkpt1-brr-data-entry ancestors gstack rcnst state) => *
 (brkpt2-brr-data-entry ancestors gstack rcnst state) => *
 (update-brr-data-1 lemma target unify-subst type-alist ancestors
                    initial-ttree gstack rcnst pot-lst whs-data) => *
 (update-brr-data-2 wonp failure-reason unify-subst gstack brr-result
                    final-ttree rcnst ancestors whs-data) => *
 })

 <p>Note that @('(set-brr-data-attachments)') is actually equivalent to
 @('(set-brr-data-attachments builtin)').  That is, the initial (built-in)
 attachments to the functions above all have the suffix,
 @('"-BUILTIN"').</p>")
other
(defxdoc with-cbd
  :parents (books-reference)
  :short "To bind the connected book directory"
  :long "<p>@('With-cbd') sets the connected book directory (see @(see cbd))
  within its scope.</p>

 @({
 Example Forms:

 ; Equivalent to (include-book "dir1/dir2/foo"):
 (with-cbd "dir1"
           (include-book "dir2/foo"))

 ; Equivalent to evaluation of the form,
 ; (include-book "arithmetic/top" :dir :system)'):
 (with-cbd (cdr (assoc-eq :system (project-dir-alist (w state))))
           (include-book "arithmetic/top"))

 })

 <p>See @(see cbd) for a description of the connected book directory.  The
 &ldquo;Technical Remark&rdquo; there, about Lisp using the @('cbd') to
 elaborate relative pathnames, applied to @('with-cbd') as well.</p>

 @({
 General Form:
 (with-cbd str form)
 })

 <p>where @('str') evaluates to a nonempty string that represents the desired
 directory (see @(see pathname)) and @('form') evaluates to an @(see
 error-triple).</p>

 <p>The effect of @('(with-cbd str form)') is to evaluate first @('(set-cbd
 str)') and then to evaluate @('form'), after which the connected book
 directory is restored to the value it had before that evaluation of
 @('set-cbd').  However, the implementation is designed so that the connected
 book directory is restored even when the evaluation of @('form') causes an
 error.</p>

 <p>The form @('(with-cbd str ev)') is an @(see event) form if @('ev') is an
 event form; thus, it may occur in @(see books) as well as @(tsee encapsulate)
 and @(tsee progn) events.  See @(see embedded-event-form).  But in an @(see
 event) context, @('str') must be a string, not merely an expression that
 evaluates to a string.</p>

 <p>Finally, note that Lisp compilers may vary in how they handle functions
 defined within the scope of @('with-cbd').  If you find an example of slower
 execution caused by using @('with-cbd'), please feel free to send it to the
 ACL2 implementors.</p>")
other
(defxdoc with-current-package
  :parents (books-reference)
  :short "To bind the @(see current-package)"
  :long "<p>Evaluation of a form @('(with-current-package "pkg" form'))
 causes @('form') to be evaluated with the @(see current-package) bound to
 @('"pkg"').</p>

 <p>Example and <b>WARNING</b>.  The current-package is not modified until
 after the form is read!  Consider the following log that was produced when the
 value of the current-package was the default, @('"ACL2"').</p>

 @({
 ACL2 !>(with-current-package "ACL2-USER"
                              (value (cw "~x0~%" 'abcd)))
 ACL2::ABCD
  NIL
 ACL2 !>
 })

 <p>We see that the call of @(tsee cw) did its printing relative to the
 @('"ACL2-USER"') package, producing output @('"ACL2::ABCD"').  This
 illustrates that the form was <i>read</i> with respect to package
 @('"ACL2"') but that its <i>evaluation</i> took place with respect to
 package @('"ACL2-USER"').</p>

 @({
 General Form:
 (with-current-package str form)
 })

 <p>where @('str') evaluates to a nonempty string that represents the desired
 package (see @(see current-package)) and @('form') evaluates to an @(see
 error-triple).</p>

 <p>Evaluation of @('(with-current-package str form)') first switches to the
 indicated package, as with @('(in-package str)'), and evaluates @('form'),
 after which the current-package is restored to the value it had before that
 evaluation of @('with-current-package').  The implementation is designed so
 that the current-package is restored even when the evaluation of @('form')
 causes an error.</p>

 <p>The following example drives home the behavior of
 @('with-current-package'); explanation follows.</p>

 @({
 ACL2 !>'common-lisp::defun
 DEFUN
 ACL2 !>'acl2-user::defun
 DEFUN
 ACL2 !>(with-current-package
         "ACL2-USER"
         (er-progn (set-current-package "ACL2-PC" state)
                   (value (cw "~x0~%" 'defun))))
 COMMON-LISP::DEFUN
  NIL
 ACL2 !>
 })

 <p>The symbol @('common-lisp::defun') is imported from the
 @('"COMMON-LISP"') package into both the @('"ACL2"') package and, as shown
 in the first two evaluation results above, the @('"ACL2-USER"') package.
 But it's not imported into the @('"ACL2-PC"') package.  The call above of
 @('with-current-package') reads @(''defun') into the current package,
 @('"ACL2"').  Then for evaluation the package changes to @('"ACL2-USER"');
 then the package is changed again to @('"ACL2-PC"') before evaluating the
 @(tsee cw) call in that package, necessitating the @('"COMMON-LISP::"')
 prefix since the @('defun') symbol in that @('cw') call is not in the
 @('"ACL2-PC"') package.  But notice that the prompt comes back as @('"ACL2
 !>"'), indicating that we are back in the @('"ACL2"') package.  The
 original package is restored after the @('with-current-package') call
 completes evaluation, even when the current-package is changed during
 evaluation.</p>

 <p>The form @('(with-current-package str ev)') is an @(see event) form if
 @('ev') is an event form; thus, it may occur in @(see books) as well as @(tsee
 encapsulate) and @(tsee progn) events.  See @(see embedded-event-form).  But
 in an @(see event) context, @('str') must be a string, not merely an
 expression that evaluates to a string.</p>

 <p>Finally, note that Lisp compilers may vary in how they handle functions
 defined within the scope of @('with-current-package').  If you find an example
 of slower execution caused by using @('with-current-package'), please feel
 free to send it to the ACL2 implementors.</p>")
other
(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>")
other
(defxdoc with-global-stobj
  :parents (stobj acl2-built-ins)
  :short "Operate on a global single-threaded object"
  :long "<p>See @(see stobj) for an introduction to single-threaded
 objects.  Also see @(see defstobj) for additional background.</p>

 <p>The @('with-global-stobj') macro is a relatively advanced utility that
 allows stobjs to be accessed directly from the ACL2 @(see state).  Examples
 may be found in @(see community-book) file
 @('books/system/tests/with-global-stobj-input.lsp'); we draw heavily from them
 below.</p>

 @({
  Example Forms:

  ; Read-only form (length 3)
  (with-global-stobj st
    ;; body:
    (fld st))

  ; Updating form (length 4; (returns state))
  (with-global-stobj
    st ; bound stobj
    (st) ; output signature of body
    ;; body:
    (update-fld x st))

  ; Updating form (length 4; returns (mv * * state st2))
  (with-global-stobj
    st ; bound stobj
    (nil st nil state st2) ; output signature of body
    ;; body:
    (let* ((st (update-fld x st))
           (st2 (update-fld2 x st2)))
      (mv (fld st) st (fld st2) state st2)))

 })

 <p>In the forms above, we call @('st') the stobj that is ``bound by'' the
 @('with-global-stobj') call, and the ``body'' of the form is the last
 argument.  The read-only form above, like all read-only forms, has a body that
 does not return the stobj bound by the form.  Each updating form above
 specifies an output signature as a list, which must contain the stobj bound by
 the form, whose elements are all @('nil') (designating a non-stobj value) or a
 stobj name.  That output signature reflects the result of the body; the entire
 form does not return the bound stobj, but does return @(tsee state), as
 explained below.</p>

 <p>@('With-global-stobj') is a macro, and the example forms above expand as
 follows.</p>

 @({
 ACL2 !>:trans1 (with-global-stobj st
                  (fld st))
  (LET ((ST (READ-USER-STOBJ-ALIST 'ST STATE)))
       (FLD ST))
 ACL2 !>:trans1 (with-global-stobj st
                  (st)
                  (update-fld x st))
  (LET ((ST (READ-USER-STOBJ-ALIST 'ST STATE)))
       (LET ((ST (UPDATE-FLD X ST)))
            (WRITE-USER-STOBJ-ALIST 'ST ST STATE)))
 ACL2 !>:trans1 (with-global-stobj st
                  (nil st nil state st2)
                  (let* ((st (update-fld x st))
                         (st2 (update-fld2 x st2)))
                    (mv (fld st) st (fld st2) state st2)))
  (LET ((ST (READ-USER-STOBJ-ALIST 'ST STATE)))
       (MV-LET ({WGS}0 ST {WGS}1 STATE ST2)
               (LET* ((ST (UPDATE-FLD X ST))
                      (ST2 (UPDATE-FLD2 X ST2)))
                     (MV (FLD ST) ST (FLD ST2) STATE ST2))
               (LET ((STATE (WRITE-USER-STOBJ-ALIST 'ST ST STATE)))
                    (MV? {WGS}0 {WGS}1 STATE ST2))))
 ACL2 !>
 })

 <p>The first illustrates that in the read-only form, the bound stobj, which is
 @('st') in that example, is bound to its value in the @('user-stobj-alist')
 field of the ACL2 @(see state).  The second and third similarly bind the
 stobj, @('st'), but then update that stobj according to the body of the
 @('with-global-stobj') call (its last argument) and then update the
 @('user-stobj-alist') of the state with that stobj's resulting value.  You can
 of course use @(':')@(tsee trans1) in this way to see expansions of other
 @('with-global-stobj') calls.</p>

 <p>Note that ACL2 expects you to use @('with-global-stobj'), not its
 expansions in terms of the @(see non-executable) functions
 @('read-user-stobj-alist'), which accesses the bound stobj from the
 user-stobj-alist of @('state'), and @('write-user-stobj-alist'), which
 completes the write for updating @('with-global-stobj') forms.  These are
 defined as follows, in terms of the ACL2 state's user-stobj-alist field, which
 maps stobj names to their values.</p>

 @({
 (defun-nx read-user-stobj-alist (st state)
   (declare (xargs :guard (symbolp st)
                   :stobjs state))
   (cdr (assoc-eq st (user-stobj-alist1 state))))

 (defun-nx write-user-stobj-alist (st val state)
   (declare (xargs :guard (symbolp st)
                   :stobjs state))
   (update-user-stobj-alist1
    (put-assoc-eq st val (user-stobj-alist1 state))
    state))
 })

 <p>@('With-global-stobj') can be useful when you want a function to read or
 write a stobj but you don't want to pass that stobj as a formal parameter.  As
 long as you pass @('state') as a formal parameter, you can access the stobj
 using @('with-global-stobj').</p>

 <p>This topic is intended to be sufficient preparation for the use of
 @('with-global-stobj').  Those who want to read more about design and
 underlying theory are welcome to peruse the (long) ACL2 source code comments,
 ``Essay on the Design of With-global-stobj'' and ``Essay on Correctness of
 Evaluation with Stobjs''.</p>

 <h3>More Examples</h3>

 <p>As noted above, examples may be found in @(see community-book) file
 @('books/system/tests/with-global-stobj-input.lsp').  Here we discuss some of
 those examples.</p>

 <p>Let us start by introducing a couple of stobjs.</p>

 @({
 (defstobj st fld)
 (defstobj st2 fld2 :congruent-to st)
 })

 <p>Calls of @('with-global-stobj') are illegal at the top level (as opposed to
 occurrences in the bodies of a definition or a theorem).</p>

 @({
 (with-global-stobj st (fld st))
 })

 <p>One solution may be to use @(tsee top-level).</p>

 @({
 (top-level (with-global-stobj st (fld st)))
 })

 <p>Normally, however, @('with-global-stobj') is used inside definition bodies.
 Here we read and write the stobj, @('st'), directly from the ACL2 @(see
 state).</p>

 @({
 (defun rd0 (state)
   (declare (xargs :stobjs state))
   (with-global-stobj st (fld st)))

 (defun wr0 (x state)
   (declare (xargs :stobjs state))
   (with-global-stobj st (st) (update-fld x st)))
 })

 <p>Let's see these in action, first writing and then reading.</p>

 @({
 ACL2 !>(wr0 2 state)
 <state>
 ACL2 !>(rd0 state)
 2
 ACL2 !>(fld st)
 2
 ACL2 !>
 })

 <p>We can use various stobj operations, even the rather fancy @(tsee
 swap-stobjs), in the body of a @('with-global-stobj') call.  The following
 events are admissible.</p>

 @({
 (update-fld 1 st)
 (update-fld 2 st2)

 (defun f3 (st2 state)
   (declare (xargs :stobjs (st2 state)))
   (with-global-stobj
     st
     (st2 st)
     (swap-stobjs st2 st)))

 (f3 st2 state)

 (assert-event (and (equal (fld st) 2)
                    (equal (fld st2) 1)))
 })

 <p>The following function writes to both @('st') and @('st2') without passing
 in either one (just @('state')).  Notice that the inner @('with-global-stobj')
 call has a body that returns the indicated values @('st') and @('st2'), but
 since @('st2') is bound by the call, it is dropped before returning from the
 call, and @('state') is added &mdash; which explains the list @('(st state)')
 supplied to the outer call.</p>

 @({
 (defun write-global-st-st2 (fld fld2 state)
   (declare (xargs :stobjs state))
   (with-global-stobj st
     (st state)
     (let ((st (update-fld fld st)))
       (with-global-stobj st2
         (st st2)
         (let ((st2 (update-fld fld2 st2)))
           (mv st st2))))))
 })

 <p>Let's check that this works as expected.</p>

 @({
 ACL2 !>(write-global-st-st2 'a 'b state)
 <state>
 ACL2 !>(fld st)
 A
 ACL2 !>(fld st2)
 B
 ACL2 !>
 })

 <p>We can also read both fields.</p>

 @({
 (defun read-global-st-st2 (state)
   (declare (xargs :stobjs state))
   (with-global-stobj st
     (with-global-stobj st2
       (list (fld st) (fld st2)))))
 })

 <p>Then, continuing with the session above:</p>

 @({
 ACL2 !>(read-global-st-st2 state)
 (A B)
 ACL2 !>
 })

 <p>We can reason about @('with-global-stobj') by reasoning about its
 expansions.  Consider the following theorem (continuing the session
 above).</p>

 @({
 (defthm rd0-of-wr0
   (equal (rd0 (wr0 val state))
          val))
 })

 <p>This fails to prove, but each of the two checkpoints has a term of the form
 @('(ASSOC-EQUAL 'ST (PUT-ASSOC-EQUAL 'ST _ _))').  That suggests the following
 lemma.</p>

 @({
 (defthm assoc-equal-put-assoc-equal
   (equal (assoc-equal key (put-assoc-equal key val alist))
          (cons key val)))
 })

 <p>This lemma proves automatically, after which @('rd0-of-wr0') proves
 automatically.</p>

 <h3>Syntax and Semantics</h3>

 <p>This section provides a reference for @('with-global-stobj').  The next
 section discusses restrictions that avoid aliasing problems.</p>

 @({
  General Forms:
  ; Read-only form (length 3):
  (with-global-stobj st form)
  ; Updating form (length 4):
  (with-global-stobj st lst form)
 })

 <p>where @('st') is the name of a @(see stobj) that is user-defined
 (i.e., not @('state')), @('form') is subject to syntactic restrictions
 discussed below, and @('lst') is a list, sometimes called an ``output
 signature''.  That list indicates the list of @('N') values returned by
 @('form'), which must include the bound stobj, @('st'): thus @('lst') is
 @('(st)') if @('N') is 1, indicating that @('form') returns an instance of
 that stobj; and otherwise @('form') returns multiple values @('(x0 x1
 ... xk)') where @('k') is @('N-1') and for each @('i'), @('xi') is either
 @('nil') if the @('i')th value is an ordinary value or else is the name of a
 stobj returned in that position (and one such stobj name is the bound
 stobj).</p>

 <p>In each General Form above, @('st') and @('form') are called the ``bound
 stobj'' and ``body'' of the @('with-global-stobj') call (respectively).</p>

 <p>For the read-only form, the bound stobj (which is @('st') above) must not
 be returned by the body of the form.</p>

 <p>For the updating form, the values actually returned are obtained by
 removing @('st') from @('lst') and then, if @('state') is not already in
 @('lst'), adding @('state') at the end of @('lst').  Consider the following
 example.</p>

 @({
 (defun f0 (st2 state)
   (declare (xargs :stobjs (st2 state)))
   (with-global-stobj
     st
     (st st2 nil state)
     (mv st st2 nil state)))
 })

 <p>In this case, @('lst') is @('(st st2 nil state)'), and the following
 expansion shows that @('st') has been dropped from the returned values.</p>

 @({
 ACL2 !>:trans1 (with-global-stobj
                  st
                  (st st2 nil state)
                  (mv st st2 nil state))
  (LET ((ST (READ-USER-STOBJ-ALIST 'ST STATE)))
       (MV-LET (ST ST2 {WGS}0 STATE)
               (MV ST ST2 NIL STATE)
               (LET ((STATE (WRITE-USER-STOBJ-ALIST 'ST ST STATE)))
                    (MV? ST2 {WGS}0 STATE))))
 ACL2 !>
 })

 <p>Evaluation of an updating @('with-global-stobj') form always
 updates @('state'): specifically it updates its @('user-stobj-alist') field
 (see @(see state)).  The following example is similar to the one above, except
 that this time the body of the @('with-global-stobj') call does not return
 state; nevertheless, the entire call does return state.  It illustrates that
 when @('state') is not in the list given as the second argument of an updating
 @('with-global-stobj') call, then the @('with-global-stobj') form not only
 drops the bound stobj from its return values but also adds @('state') as the
 last returned value (or, if the bound stobj was the sole symbol in the list,
 then the call returns @('state') as the sole value).</p>

 @({
 ACL2 !>:trans1 (with-global-stobj
                  st
                  (st st2 nil)
                  (mv st st2 nil))
  (LET ((ST (READ-USER-STOBJ-ALIST 'ST STATE)))
       (MV-LET (ST ST2 {WGS}0)
               (MV ST ST2 NIL)
               (LET ((STATE (WRITE-USER-STOBJ-ALIST 'ST ST STATE)))
                    (MV? ST2 {WGS}0 STATE))))
 ACL2 !>
 })

 <p>Note that because @('with-global-stobj') updates @('state'), then
 @('state') must be a known stobj when @('with-global-stobj') is called.  In
 particular, in order to call @('with-global-stobj') in the body of a function,
 @('state') should be a formal parameter of that function.</p>

 <h3>Syntactic Restrictions to Avoid Aliasing</h3>

 <p>For the examples in this section, we continue to assume that the following
 @(tsee defstobj) @(see events) have been evaluated.</p>

 @({
 (defstobj st fld)
 (defstobj st2 fld2 :congruent-to st)
 })

 <p>Consider the following definition.</p>

 @({
 (defun foo (st state)
   (declare (xargs :stobjs (st state)))
   (let ((state (with-global-stobj st
                  (st)
                  (update-fld 3 st))))
     (mv (fld st) state)))
 })

 <p>ACL2 admits that form, but causes an error with the following call of
 @('foo').</p>

 @({
 ACL2 !>(foo st state)


 ACL2 Error in TOP-LEVEL:  Illegal top-level form, (FOO ST STATE).
 The stobj ST occurs free, yet may be bound by an updating WITH-GLOBAL-
 STOBJ form, as the top-level form calls FOO, which makes an updating
 WITH-GLOBAL-STOBJ call that binds ST.  See :DOC with-global-stobj.

 ACL2 !>
 })

 <p>Let us see why this call must be illegal; then we'll study the error
 message.  The @('with-global-stobj') form above will set the field, @('fld'),
 of @('st') to the value, 3.  Moreover, ACL2 uses destructive update on stobjs:
 the actual Lisp object representing @('st') has value 3 in its field, and this
 is the same object for which we return @('(fld st)') from @('foo').  So if
 @('(foo st state)') were allowed to execute, it would return the multiple
 values @('(3 <state>)').  However, ACL2 can prove that ACL2 returns @('(fld
 st)') unchanged:</p>

 @({
 (thm (implies (stp st)
               (equal (mv-nth 0 (foo st state))
                      (fld st))))
 })

 <p>What we are seeing is a violation of single-threadedness.</p>

 <p>Now let's look at the error message above.  It explains that ``the stobj ST
 occurs free'' in @('(foo st state)'): indeed, @('st') is the first argument of
 that call.  Therefore, @('st') can be accessed in that top-level form; indeed,
 we have seen that it is returned as the first value.  However, @('st') can
 also be destructively modified because of the updating @('with-global-stobj')
 call in the body of @('foo'): ``the top-level form calls FOO, which makes an
 updating WITH-GLOBAL-STOBJ call that binds ST.''  As we have discussed, that
 updating call destroys single-threadedness, and hence must be avoided.  We may
 call this an ``aliasing problem'', since the bound stobj shares structure with
 the formal parameter.</p>

 <p>By contrast, there is no such problem if we replace @('st') by its
 congruent stobj, @('st2'), in the top-level call.</p>

 @({
 ACL2 !>(foo st2 state)
 (NIL <state>)
 ACL2 !>(fld st2)
 NIL
 ACL2 !>(fld st)
 3
 ACL2 !>
 })

 <p>In this case there is no aliasing problem.  The formal parameter @('st') of
 @('foo') is bound to the (global) value of @('st2'), which does not share
 structure with the (global) value of stobj @('st') that is updated by the
 @('with-global-stobj') form.</p>

 <p>Note that the aliasing problem can be buried through a chain of function
 calls, as we now illustrate.  Function @('foo2') is like @('foo') above, with
 two changes: instead of updating the field with @('3') we update it with the
 formal parameter, @('val'); and that update is done inside the called
 function, @('foo2-sub'), rather than directly in the body of @('foo2').</p>

 @({
 (defun foo2-sub (val state)
   (declare (xargs :stobjs state))
   (with-global-stobj st
     (st)
     (update-fld val st)))

 (defun foo2 (val st state)
   (declare (xargs :stobjs (st state)))
   (let ((state (foo2-sub val state)))
     (mv (fld st) state val)))
 })

 <p>The error message is essentially the same, except that the chain of calls
 is shown that leads to the problematic updating @('with-global-stobj') form.
 The behavior on @('st2') instead of @('st') is fine, as before.</p>

 @({
 ACL2 !>(foo2 3 st state)


 ACL2 Error in TOP-LEVEL:  Illegal top-level form, (FOO2 3 ST STATE).
 The stobj ST occurs free, yet may be bound by an updating WITH-GLOBAL-
 STOBJ form, as the top-level form calls FOO2, which calls FOO2-SUB,
 which makes an updating WITH-GLOBAL-STOBJ call that binds ST.  See
 :DOC with-global-stobj.

 ACL2 !>(foo2 4 st2 state)
 (NIL <state> 4)
 ACL2 !>(fld st2)
 NIL
 ACL2 !>(fld st)
 4
 ACL2 !>
 })

 <p>So far we have seen just one aliasing problem, i.e., between a free stobj
 in a top-level form and a subsidiary updating @('with-global-stobj') form.
 Another case is where the free stobj in a top-level form is actually
 returned (we might say, updated) by that form; in that case, any subsidiary
 @('with-global-stobj') form is problematic, even if it is read-only.  Here is
 an example.</p>

 @({
 (defun g2 (val st state)
   (declare (xargs :stobjs (st state)))
   (let ((st (update-fld val st)))
     (let ((f (with-global-stobj st (fld st))))
       (mv f (fld st) st state))))

 (g2 nil st state)
 })

 <p>As before, the definition is fine, but the ensuing top-level call is not.
 And as before, if we replace the top-level stobj occurrence by one that is
 congruent to @('st'), there is no error: @('(g2 5 st2 state)').</p>

 <p>Note that there is no aliasing problem when there is no update of the
 stobj, either in the top-level form or in the subsidiary
 @('with-global-stobj') form.  The following are perfectly legal, for
 example.</p>

 @({
 (defun g1 (st state)
   (declare (xargs :stobjs (st state)))
   (let ((f (with-global-stobj st (fld st))))
     (mv f state (fld st))))

 (g1 st state)
 })

 <p>So far we have seen two similar error cases due to aliasing: both are
 top-level calls involving a stobj occurrence that has an occurrence below
 bound by @('with-global-stobj'), where at least one of the two occurrences
 updates the stobj.  Consider this: a top-level call like @('(foo st state)')
 could be viewed as grabbing @('st') from the ACL2 state, hence could be viewed
 as being @('(with-global-stobj st (foo st state))').  So we can think of the
 restrictions as being about nested @('with-global-stobj') calls, and that
 leads us to the final two cases.  Here is a summary of all the restrictions to
 prevent aliasing, starting with the two discussed above about top-level
 evaluation, and ending with the two new ones about nested
 @('with-global-stobj') calls.</p>

 <ul>

 <li>In a form @('u') that is legal at the top-level, where @('u') has a free
 occurrence of stobj @('st'), there is no updating @('with-global-stobj') call
 that binds @('st') and is invoked during evaluation of @('u').</li>

 <li>In a form @('u') that is legal at the top-level, where @('u') returns
 stobj @('st'), there is no @('with-global-stobj') call that binds @('st') and
 is invoked during evaluation of @('u').</li>

 <li>In a form @('(with-global-stobj st u)'), there is no
 updating @('with-global-stobj') call that binds @('st') and is invoked during
 evaluation of @('u').</li>

 <li>In an updating form @('(with-global-stobj st lst u)'), there is no
 @('with-global-stobj') call that binds @('st') and is invoked during
 evaluation of @('u').</li>

 </ul>

 <p>Our restrictions that prevent aliasing are syntactic ones, sufficient to
 prevent the invocations described above.  They are implemented by searching
 for calls of @('read-user-stobj-alist') to identify expansions of
 @('with-global-stobj') calls, and by searing for calls of
 @('write-user-stobj-alist') to identify expansions of updating
 @('with-global-stobj') calls.</p>

 <p>Finally, we note that the syntactic restrictions extend to @(see guard)s.
 Consider again the function @('rd0') as defined above, and let's use it in the
 guard of a function.</p>

 @({
 (defun rd0 (state)
   (declare (xargs :stobjs state))
   (with-global-stobj st (fld st)))

 (defun call-rd0-in-guard (state)
   (declare (xargs :stobjs state
                   :guard (rd0 state))
            (ignore state))
   17)
 })

 <p>Then as before, it is an error for a top-level form to update @('st') and
 also call a function that may lead to a @('with-global-stobj') call that binds
 @('st').</p>

 @({
 ACL2 !>(let ((st (update-fld 3 st)))
          (mv st (call-rd0-in-guard state)))


 ACL2 Error in TOP-LEVEL:  Illegal top-level form,
 (LET ((ST (UPDATE-FLD 3 ST))) (LIST ST (CALL-RD0-IN-GUARD STATE))).
 The stobj ST is returned by evaluation of that form, yet is bound by
 a WITH-GLOBAL-STOBJ form, as the top-level form calls CALL-RD0-IN-GUARD,
 which calls RD0, which makes a WITH-GLOBAL-STOBJ call that binds ST.
 See :DOC with-global-stobj.

 ACL2 !>
 })

 <h3>Constrained Functions and Defattach</h3>

 <p>Consider the following constrained function introduction.</p>

 @({
 (encapsulate
   (((crn0 state) => *))
   (local (defun crn0 (state)
            (declare (xargs :stobjs state))
            (state-p state))))
 })

 <p>If we try to attach @('rd0') (defined above) to @('crn0') we get an error,
 as shown just below.  In short, this error says that since @('rd0') may lead
 to a call of @('with-global-stobj') that binds @('st'), then with this
 attachment, @('crn0') may lead to such a call; yet there is no record in the
 @(see world) that @('crn0') may lead to such a call.</p>

 @({
 ACL2 !>(defattach crn0 rd0)


 ACL2 Error in ( DEFATTACH CRN0 RD0):  The attachment of RD0 to CRN0
 restricts stobjs bound by WITH-GLOBAL-STOBJ under calls of RD0, according
 to the :GLOBAL-STOBJS keyword (default nil) in the signature introducing
 CRN0.  But this restriction is violated for stobj ST:  the attempt
 is to attach RD0, which makes a WITH-GLOBAL-STOBJ call that binds ST,
 yet that stobj is not specified by the :GLOBAL-STOBJS keyword of CRN0.
 See :DOC with-global-stobj.


 Summary
 Form:  ( DEFATTACH CRN0 RD0)
 Rules: NIL
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)

 ACL2 Error [Failure] in ( DEFATTACH CRN0 RD0):  See :DOC failure.

 ******** FAILED ********
 ACL2 !>
 })

 <p>The solution is to note, in the signature of the constrained function, that
 it may lead to a @('with-global-stobj') call.  This is accomplished by using
 the keyword, @(':GLOBAL-STOBJS'), in the signature of the function.  The value
 of that keyword is @('nil') by default, indicating that there is no such call.
 Otherwise the value is a cons of the form @('(r . w)'), where @('r') and
 @('w') are disjoint lists of stobjs.  Their interpretation is as follows:
 @('w') includes all stobjs for which an attachment may have an updating
 @('with-global-stobj') call, and @('r') includes all stobjs not in @('w') for
 which an attachment may have a @('with-global-stobj') call.  Consider the
 following modification of the @(tsee encapsulate) form above.</p>

 @({
 (encapsulate
   (((crn1 state) => * :global-stobjs ((st) . nil)))
   (local (defun crn1 (state)
            (declare (xargs :stobjs state))
            (state-p state))))
 })

 <p>Then the form @('(defattach crn1 rd0)') is legal: unlike @('crn0'),
 @('crn1') has specified that @('st') may be bound by @('with-global-stobj') in
 an attachment.</p>

 <p>The requirement is thus as follows.  Consider attachment of @('g') to a
 constrained function @('f'), where @('g') may lead to updating
 @('with-global-stobj') calls that bind stobjs @('w1'), @('w2'), ..., @('wk'),
 and also @('g') may lead to @('with-global-stobj') calls that bind, in
 addition to the @('wi'), stobjs @('r1'), @('r2'), ..., @('rn').  Then the
 signature of @('f') must specify a value @('(r . w)') for the keyword
 @(':GLOBAL-STOBJS'), where @('r') and @('w') are lists of stobjs such that:
 @('w') includes all @('wi'), and the union of @('r') and @('w') includes all
 @('ri').</p>")
other
(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))))
 })")
other
(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>")
other
(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>")
other
(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 essentially
 @(see untouchable), defined with @(tsee defmacro-untouchable); @(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>")
other
(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
 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))))
 })

 <p>Note for ACL2(p) users: When @(see parallel-execution) is enabled,
 invocations of @('with-local-state') are surrounded by a lock.</p>")
other
(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.  Also see @(see defstobj) for additional background.</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 only allowed via
 @('with-local-stobj') or 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') &mdash; in fact, if @('mv-let-form') is @('(mv-let (...)
 ... body)'), then @('body') does not even reference @('stobj-name') &mdash;
 and if @('creator-name') is supplied then it should be the name of the creator
 function for @('stobj-name').  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>Note that if a stobj @('ST') is bound upon beginning evaluation of a form
 @('(with-local-stobj ST ...)'), then the value of @('ST') is the same
 immediately before evaluating that form as it is immediately after that
 evaluation.  In other words, only a local version of @('ST') is modified
 inside that @('with-local-stobj') form.</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
 })")
other
(defxdoc with-output
  :parents (output-controls)
  :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>

 <h3>Examples</h3>

 @({
  ; Turn off all controllable output during evaluation of the indicated thm form.
  (with-output
   :off :all
   :gag-mode nil
   :inhibit-er-hard t
   (thm (equal (app (app x y) z) (app x (app y z)))))

  ; Equivalent to the example just above.
  (with-output
   :off :all!
   (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-off :all
     :gag-mode :goals
     (defthm app-assoc (equal (app (app x y) z) (app x (app y z)))))

  ; Turn off all but the ``time'' and ``rules'' parts of the summary.
  (with-output
     :on summary
     :summary-off (:other-than time rules)
     :gag-mode :goals ; default: 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 with output types made explicit
  ; (that is, using 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)))

  ; The following use of :ctx causes the error message to start with
  ; ``ACL2 Error in MY-CUSTOM-CTX'' instead of
  ; ``ACL2 Error in ( DEFUN FOO ...)''.
  (with-output
   :ctx 'my-custom-ctx
   (defun foo (x) y))
 })

 <h3>General Form</h3>

 @({
  (with-output :key1 val1 ... :keyk valk form)
 })

 <p>where @('form') should evaluate to an @(see error-triple).  That evaluation
 takes place with output that is according to the values @('vali') of the
 keywords, @(':keyi'), as described below.  When the scope of @('with-output')
 is exited, then all modifications are undone, including the states of output
 and summary inhibition, @(tsee gag-mode), and @(see evisc-tuple)s.  Each
 keyword may occur at most once.</p>

 <p>Use of the argument @(':off :all!') is treated exactly the same as using
 arguments @(':off :all :gag-mode nil').  We assume below that any use of
 @(':off :all!')  has been expanded away in that manner.</p>

 <h3>On-off specs</h3>

 <p>Before discussing the keywords we introduce the notion of ``on-off specs'',
 which are the legal values of the keywords @(':on'), @(':off'),
 @(':summary-on'), and @(':summary-off').  (As noted above, we  ignore
 @(':off :all!') below, as it is just an abbreviation for @(':off :all
 :gag-mode nil').)  An on-off spec has one of the following forms, where each
 @('symi') is a symbol, and subject to restrictions discussed below</p>

 <ul>

 <li>@(':all')</li>

 <li>@('sym') ; a symbol that is not @(':all')</li>

 <li>@('(sym1 ... symk)')</li>

 <li>@('(:other-than sym1 ... symk)')</li>

 </ul>

 <p>The set of ``associated valid symbols'' is defined as follows.  For
 @(':off') or @(':on'), these symbols are the <i>output types</i> that can be
 inhibited &mdash; that is, members of the list stored in the constant
 @('*valid-output-names*'), which is the list @(`*valid-output-names*`) &mdash;
 and they are treated as in @(tsee set-inhibit-output-lst).  Similarly, for
 @(':summary-on') or @(':summary-off'), these are the <i>summary types</i>: the
 parts of the @(see summary) that can be inhibited as in @(tsee
 set-inhibited-summary-types), that is, members of the list stored in the
 constant @('*summary-types*'), which is the list @(`*summary-types*`).  An
 on-off spec consisting of associated valid symbols, @('(sym1 ... symk)'),
 indicates the set of symbols, @('{sym1,...,symk}').  The other legal forms of
 on-off spec and their meanings are as follows: @(':all') represents the set of
 all associated valid symbols, any other symbol @('sym') abbreviates
 @('(sym)'), and @('(:other-than sym1 ... symk)') represents the set of
 associated valid symbols that are not in the list @('(sym1 ... symk)').</p>

 <p>Note that these two notions of ``associated valid symbols'' &mdash; the
 <i>output types</i> controlled by keywords @(':on') and @(':off'), and the
 <i>summary types</i> controlled by keywords @(':summary-on') and
 @(':summary-off') &mdash; operate independently in the following sense.  The
 keywords @(':on') and @(':off') control output types from the list
 @('*valid-output-names*') displayed above, one of whose members is
 @('SUMMARY').  The keywords @(':summary-on') and @(':summary-off') control
 summary types from the list @('*summary-types*') displayed above, indicating
 which types of summary are to be printed in the case that @('SUMMARY') is
 among the output types that are on.  This summary control persists even as the
 @('SUMMARY') type changes state between off and on.  Consider the following
 example.</p>

 @({
  (with-output :off (summary)
   (with-output :summary-off (time)
    (with-output :on (summary)
     (thm (equal (car (append x y)) (if (consp x) (car x) (car y)))))))
 })

 <p>The resulting output does not include @('TIME') output in the summary.  The
 reason is that the second @('with-output') form specifies that @('TIME')
 summary output is off; then when the third (innermost) output turns
 @('SUMMARY') output on, still, the @('TIME') summary output is off, so the
 @('THM') call does not print the @('TIME') part of the summary output.  Note
 that the same reasoning applies if the third @('with-output') call above
 specifies @(':on :all') instead of @(':on (summary)'); that case also produces
 no time output in the summary.  That is, the use of @(':on :all') specifies
 which output types are on, but does not affect which summary types are on;
 again, output types and summary types are controlled independently by the
 respective pairs @(':on/:off') and @(':summary-on/:summary-off').</p>

 <h3>Keyword arguments</h3>

 <p>We turn now to a discussion of the keyword arguments.</p>

 <p>@(':on'), @(':off')</p>

 <p>The values for these keywords, which are not evaluated, must be on-off
 specs for these keywords (as discussed above).  If @(':on :all') is specified,
 then then every output type is turned on except for those in the set specified
 by the value of @(':off').  Otherwise, if @(':off :all') is specified, then
 every output type is inhibited except as specified by the value of
 @(':on').  Otherwise @(':all') is not specified for either @(':on') or
 @(':off'), and the currently-inhibited output types are reduced as specified
 by the value of @(':on') and then extended as specified by the value of
 @(':off').</p>

 <p>@(':summary-on'), @(':summary-off')</p>

 <p>The values for these keywords, which are not evaluated, must be on-off
 specs for these keywords.  They are interpreted exactly as are the values for
 @(':on') and @(':off') as described above, except that instead of output types
 they are interpreted with respect to the summary types (i.e., in the
 terminology introduced above, with respect to the set of associated valid
 symbols for @(':summary-on') and @(':summary-off')).</p>

 <p>@(':gag-mode')</p>

 <p>The value should evaluate to one of the legal values for @(tsee
 set-gag-mode).  The effect is as though @('set-gag-mode') has been called with
 this argument, before modifying how output is inhibited, at the start of
 evaluating the given form.</p>

 <p>@(':evisc')</p>

 <p>The value should evaluate to 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') and @(':brr') (that is, a member of
 the list @(`(set-difference-eq *evisc-tuple-sites* '(:trace :brr))`)), and
 each value evaluates to a legal @(see evisc-tuple) for that keyword.  The
 effect is as though @('set-evisc-tuple') has been called, before modifying how
 output is inhibited, with this argument at the start of evaluating the given
 form.</p>

 <p>@(':ctx')</p>

 <p>The value should evaluate to a context &mdash; see @(see ctx) &mdash; that
 will generally be used throughout evaluation of the given form, in place of
 the usual event context (including the @('"Form"') field of the @(see
 summary)).</p>

 <p>@(':stack')</p>

 <p>The value, which is not evaluated, must be @(':push') or @(':pop').  The
 effect of @(':push') is essentially to create a new environment for inferior
 calls of @('with-output') that can be reverted (popped) by inferior calls of
 @('with-output'), as discussed in the next section.  Note that the handling of
 the @(':stack') argument pays no attention to the @(':summary-on') or
 @(':summary-off') arguments.</p>

 <p>@(':inhibit-er-hard')</p>

 <p>By default, ACL2 prints messages for hard errors &mdash; errors whose
 message starts with &ldquo;HARD ACL2 ERROR&rdquo; &mdash; even when @('error')
 output is inhibited (whether by using the keyword, @(':off'), or by calling
 @(tsee set-inhibit-output-lst)).  This behavior holds when @(see state) global
 @('inhibit-er-hard') has its default value of @('nil'); see @(see
 set-inhibit-output-lst).  When keyword @(':inhibit-er-hard') is supplied an
 expression, the value @('v') of that expression overrides the global value of
 @('inhibit-er-hard'): thus when error output is inhibited, hard error messages
 are printed if @('v') is @('nil') and they are not printed if @('v') is not
 @('nil').  Note that this behavior automatically takes place when
 @('with-output') is supplied the arguments @(':off :all!'), but not
 @(':off :all').</p>

 <h3>More about the @('stack') argument</h3>

 <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 cons of the values of
 @(see state) globals @('inhibit-output-lst') and @('gag-mode') 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 provides the values of @(see state) globals
 @('inhibit-output-lst') and @('gag-mode').</p>

 <h3>Concluding remarks</h3>

 <p>@('With-output') has no effect in raw Lisp, in the sense that a call
 @('(with-output ... form)') macroexpands to @('form') in raw Lisp.  Normally
 this produces desired behavior, but occasionally you may be a bit surprised.
 Consider for example the following book.</p>

 @({
 (in-package "ACL2")

 (with-output
   :off :all
   (make-event (prog2$ (cw "@@@ NOISE @@@")
                       '(defun f (x) x))
               :check-expansion t))

 (make-event (with-output!
               :off :all
               (value (prog2$ (cw "@@@ QUIET @@@")
                              '(defun g (x) x))))
             :check-expansion t)
 })

 <p>When certifying this book, we do not see either &lsquo;@('NOISE')&rsquo; or
 &lsquo;@('QUIET')&rsquo;.  But then when we include this book, we see
 &lsquo;@('NOISE')&rsquo; (but not &lsquo;@('QUIET')&rsquo;).  To see why, we
 first note that both events are evaluated in raw Lisp when including the
 book (as discussed briefly in the documentation topic, @(see
 book-compiled-file)).  The first calls @('with-output'), which (as noted
 above) disappears during macroexpansion.  The second calls @('with-output!'),
 which has the desired effect of suppressing output.</p>")
other
(defxdoc with-output-lock
  :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 !>
 })")
other
(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>")
other
(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>")
other
(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$-fn 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>You can get the current serialize-character as follows.</p>

 @({
 (get-serialize-character state)
 })

 <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>")
other
(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>")
other
(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 or brr evisc-tuples, so
 trace and brr output are 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').  It actually returns the useless value @('(mv nil
 :invisible state)'), except that if an error is detected then it generally
 returns @('(mv t nil state)'), indicating an error; see @(see error-triple).
 So do not use @('without-evisc') in programs if you want the value of the
 computation to be returned, rather than merely printed.  (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)'); see @(see
 walkabout).</p>")
other
(defxdoc wof
  :parents (output-controls 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>")
other
(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 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>")
other
(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)') when in the wormhole.  This is
 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 it is modified while in the wormhole and we 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, named @(tsee brr), to implement the @(see
 break-rewrite) 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 @('wormhole'), @(tsee wormhole-eval), or @(tsee
 set-persistent-whs-and-ephemeral-whs) is called.  However, it is forbidden to
 invoke these functions on any name listed in
 @('*protected-system-wormhole-names*'), which includes @('brr') (the @(see
 break-rewrite) wormhole name), @('accumulated-persistence'), and
 @('fc-wormhole') (the name of the wormhole managing @(see
 forward-chaining-reports)), among others.</p>

 <p>Every wormhole name has a ``status.''  The status of a wormhole is stored
 outside of ACL2 at a location known to hold the ``persistent wormhole status''
 or ``persistent-whs'' of that wormhole.  Before @('wormhole') enters its
 read-eval-print loop the persistent-whs is assigned to the state global
 variable @('wormhole-status') and so while inside the wormhole the status is
 available as @('(@ wormhole-status)').  @('Wormhole-status') is untouchable:
 you cannot change it directly as with @('(assign wormhole-status ...)').  But
 the persistent-whs can be changed, e.g., with @('wormhole'),
 @('wormhole-eval'), or @('set-persistent-whs-and-ephemeral-whs').  See @(tsee
 wormhole-status) for a discussion of the ramifications of there being two
 places a wormhole's status might be found and of the importance of the notion
 of ``wormhole coherence.''</p>

 <p>Upon the first call on name of @('wormhole') (or the other wormhole creator
 functions mentioned above) 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
 by set in the @('form') argument of @('wormhole') using
 @('set-persistent-whs-and-ephemeral-whs') or @(tsee
 sync-ephemeral-whs-with-persistent-whs).</p>

 <p>The @('car') of the status should be either @(':ENTER') or @(':SKIP') and
 is called the wormhole's ``entry code.''  The entry code of @('nil') or,
 indeed, of any value other than @(':SKIP') is treated as thought it were
 @(':ENTER').  The @('cdr') of the status is arbitrary data maintained by the
 author of the wormhole.</p>

 <p>When the wormhole is exited &mdash; typically because the form @(':q') was
 read by @('ld') &mdash; the then-current ephemeral-whs (i.e., (@
 wormhole-status)) is moved to the persistent-whs so that it can be restored
 when this wormhole is entered again.  (Note: The break-rewrite wormhole,
 @('brr'), is handled differently.  When it is exited back to the top-level,
 the persistent-whs is set to what it was when ACL2 was last at the top-level.)
 The rest of the wormhole state is lost upon exit.</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)') and may be assigned with @(tsee
 assign).</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 exit the wormhole.</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 persistent-whs with @(tsee wormhole-eval).
 That @('lambda') application must produce a new wormhole status, which is
 stored as the wormhole's new persistent-whs.  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 @(':SKIP') the wormhole state is
 not manufactured; the new persistent-whs is merely saved and @('wormhole')
 returns nil.  Otherwise, a new state is manufactured and 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>See @(tsee wormhole-programming-tips) for some advice about using wormholes,
 maintaining (or not maintaining) coherence, etc.</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').  The wormhole in question will be named @('demo') and it is
 created in the answer to the first question below.  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 initialize the status of the @('demo') wormhole?</p>

 <p>Actually, it is often unnecessary to explicitly initialize the status of a
 new wormhole because it is @('nil') by default, the @(tsee
 wormhole-entry-code) of @('nil') is @(':enter') and the @(tsee wormhole-data)
 of @('nil') is @('nil'), which often is enough.  But if the data field of your
 wormhole needs more structure for whatever you're planning to do with it to
 make sense, you can initialize it by executing a form like this, where the
 @('nil') below is the contents of the initial data field.</p>

 @({
 ACL2 !>(wormhole-eval 'demo
                       '(lambda (whs) (make-wormhole-status whs :enter nil))
                       nil)
 NIL
 ACL2 !>(get-persistent-whs 'demo state)
  (:ENTER)
 })

 <p><b>Q.</b> How do I define a function that prints the (persistent) status of
 the @('demo') wormhole 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 the @('prog2$') above.  After printing the status to the comment
 window we return the unchanged status @('whs').  Had we just written the
 @('cw') term, which returns @('nil'), without then returning @('whs'), the
 function would print the status and then set it to @('nil')!</p>

 <p><b>Q.</b> How can I define a function, @('demo-collect'), that does not
 take or return @(tsee state) but that can collect every symbol passed to
 it (but not collect non-symbols)?</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.  Note that the @('lambda') expressions used in both definitions
 mention @('x') as a free variable.</p>

 <p><b>Q.</b> How do I use @('demo-collect')?  Below we show an interactive
 session log with @('demo-collect') and @('demo-status').  Notice that
 @('state') is nowhere involved but that the functions always return @('nil').
 The computation, collection, and printing are done inside the wormhole.</p>

 @({
 ACL2 !>(demo-status)
 DEMO status:
 (:ENTER)
 NIL
 ACL2 !>(demo-collect 'a)
 NIL
 ACL2 !>(demo-status)
 DEMO status:
 (:ENTER A)
 NIL
 ACL2 !>(demo-collect 'b)
 NIL
 ACL2 !>(demo-collect 'c)
 NIL
 ACL2 !>(demo-status)
 DEMO status:
 (:ENTER C B A)
 NIL
 })

 <p><b>Q.</b> How do I reset the data to @('nil')?</p>

 <p>The answer is the same as the answer to the first question, use
 @('wormhole-eval') as we did there.  But we'll repeat it as a session
 log because in the next question we want the data field to start off at @('nil')
 again.</p>

 @({
 ACL2 !>(wormhole-eval 'demo
                       '(lambda (whs) (make-wormhole-status whs :enter nil))
                       nil)
 NIL
 ACL2 !>(demo-status)
 DEMO status:
 (:ENTER)
 NIL
 })

 <p><b>Q.</b> How can I use @('demo-collect') in a function?  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.  We illustrate a
 call below.</p>

 @({
   (defun my-len (lst)
     (if (endp lst)
         0
         (+ 1
            (prog2$ (demo-collect (car lst))
                    (my-len (cdr lst))))))
 })

 <p>Thus, for example, if we call @('my-len') on a list of length @('5') it
 returns @('5') but accumulates the symbols into the @('demo') wormhole,
 without @('state').  From a logical perspective @('my-len') is just @('len')
 and that can be proved trivially.</p>

 @({
  ACL2 !>(my-len '(4 temp car "Hi" fix))
  5
  ACL2 !>(demo-status)
  DEMO status:
  (:ENTER FIX CAR TEMP)
  NIL
  ACL2 !>(thm (equal (my-len x) (len x)))
  ...
  Proof succeeded.
  })

 <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 data,
 since we cannot rely on the invariant that no other function interferes with
 the status of the @('demo') wormhole.  In the case that the data is not a
 true-list we act like the data is @('nil') and set the status 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 FIX CAR TEMP)
  NIL
  ACL2 !>(demo-set-entry-code 'fix)
  NIL
  ACL2 !>(demo-status)
  DEMO status:
  (:ENTER FIX CAR TEMP)
  NIL
  ACL2 !>
 })

 <p>We won't be using @('demo-set-entry-code') again in these questions and
 answers, so don't spend time learning more about it!</p>

 <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 demo-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, wormhole will 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~%~
                                  Exit with :q~%~%"
                                (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'' &mdash; so called because it is the first form executed
 by the wormhole's read-eval-print loop &mdash; is the quoted
 @('if')-expression in the fourth argument of @('wormhole').  It asks whether
 the @('wormhole-input')
 (i.e., @('x')) has an @('absolute-event-number') property.</p>

 <p>The true branch of that @('if') is 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 and being prompted
 for input.  We continue in the loop until the user types @(':q').</p>

 <p>The false branch of the @('if') is taken when @('x') 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>every time 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>Had we defined @('demo-collect-symbols-and-print-events') before @('my-len')
 we could have called it instead of @('demo-collect').  Then</p>

 @({
  ACL2 !>(my-len '(4 temp car "Hi" fix))
 })

 <p>would have still collected all the symbols into the @('demo') wormhole, but
 on the symbols @('car') and @('fix') it would have entered an interactive
 break.  Here is the break that would be triggered when this version of
 @('my-len') encounters the @('fix').</p>

 @({
 Entering a wormhole on the event name FIX
 Exit with :q

 V     -8055  (DEFUN FIX (X)
                 (DECLARE (XARGS :GUARD T :MODE :LOGIC))
                 (IF (ACL2-NUMBERP X) X 0))
 Wormhole ACL2 !>(fix 123)
 123
 Wormhole ACL2 !>(fix t)
 0
 Wormhole ACL2 !>:q
 })

 <p>After printing the @('(DEFUN FIX ...)') above the user in this session
 called @('fix') twice to see how it behaves.  Then the user issued the @(':q')
 command to exit the interactive loop, allowing @('my-len') to continue.  When
 @('my-len') finishes processing the list, it would return @('5').</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>")
other
(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>")
other
(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>")
other
(defxdoc wormhole-eval
  :parents (wormhole)
  :short "State-saving without @(see 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 as described below.  It is forbidden to invoke
 @('wormhole-eval') on the names listed in
 @('*protected-system-wormhole-names*'), which includes @('brr') (the @(see
 break-rewrite) wormhole name), @('accumulated-persistence'), and
 @('fc-wormhole') (the name of the wormhole managing @(see
 forward-chaining-reports)), among others.</p>

 <p>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 persistent-whs (see @(tsee wormhole-status)) of
 the named wormhole and remembers the value as the new persistent-whs.  If the
 @('lambda') has no formal parameter, the @('lambda') is applied to no
 arguments and the value is the new persistent-whs.  @('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 the persistent-whs, but the results
 remain hidden.  To interact with the wormhole's state you must use @(tsee
 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>@('Wormhole-eval') is intended to be fast, but it is further optimized when
 the given @('lambda') is of the following form.  In this case
 @('wormhole-eval') returns immediately when the @(tsee wormhole-data) is
 @('nil'), which is reasonable since the old and new status are equal in this
 case.</p>

 @({
 (lambda (whs)
         (let ((info (wormhole-data whs)))
                 (cond ((null info) whs)
                       ...)))
 })

 <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>")
other
(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 persistent-whs and the result is
 stored as the new persistent-whs.  Then, if the entry-code of the new status
 is @(':ENTER') (actually, if it is not @(':SKIP')), @(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 variables @('wormhole-name'), @('wormhole-input') and
 @('wormhole-status') are assigned @('name'), the value of @('input') and the
 persistent-whs, respectively.  Thus, inside the wormhole, @('(@
 wormhole-name)') returns the name of the current wormhole, @('(@
 wormhole-input)') returns the list of inputs, @('(@ wormhole-status)') returns
 the ephemeral-whs.  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 ephemeral-whs is written to the persistent-whs
 and the wormhole state ``evaporates.''  The next time the wormhole is entered
 its ephemeral-whs will be what it was when it last exited.</p>

 <p>Here is what really happens.</p>

 <p>Each wormhole's persistent-whs 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*').  However, be cautious about
 printing it because the persistent-whs of some wormholes can be quite large.
 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.  @(csee Guard) @(see clause)s 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 wormhole
 status.</p>

 <p>If the newly computed status has an entry code other than @(':SKIP') @(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, @('*wormholep*'), 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.  Then we assign the three state globals
 @('wormhole-name'), @('wormhole-input'), and @('wormhole-status').  Those
 assignments are made undoably since @('*wormholep*') is set.</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'), the first read from this @('standard-oi') returns @('form') and
 subsequent reads, if any, come from @('*standard-oi*').  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
 @('*wormholep*') 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 ephemeral-whs is transferred to
 the persistent-whs, i.e., the final value of @('(@ wormhole-status)') is
 stored under the current @('wormhole-name') in @('*wormhole-status-alist*')
 and then the accumulator is used to ``undo'' all the state changes.</p>

 <p>@('Wormhole') always returns @('nil').</p>

 <p>The system wormhole named @('brr'), which implements @(see break-rewrite),
 is treated a little differently.  When @('ld') exits due to an abort the
 ephemeral-whs is not transferred to the persistent-whs.  Instead, the
 persistent-whs is set to what it was at the time break-rewrite was first
 entered from the top-level.  See the Essay on Break-Rewrite in the source code
 file @('rewrite.lisp') for details about the implementation of break-rewrite,
 which is intimately connected to wormholes.</p>")
other
(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>")
other
(defxdoc wormhole-programming-tips
  :parents (wormhole wormhole-eval)
  :short "some tips for how to use wormholes"
  :long "<p>Wormholes allow one to collect data and print without having access
  to ACL2's @(tsee state).  Many ACL2 utilities are implemented in terms of
  wormholes.  Examples include @(see break-rewrite), @(tsee
  accumulated-persistence), and @(tsee forward-chaining-reports).  So an ACL2
  developer wishing to add features or fixing misbehaviors in these system
  utilities must be familiar with programming wormholes.  But users might also
  employ wormholes to implement utilities in their own models.  Thus, this
  documentation topic is as much for future ACL2 developers and maintainers as
  for ACL2 users (but items meant primarily for developers often include
  references to functions in the ACL2 source code which other users may just
  ignore).  This is simply a list of tips for a person programming with
  wormholes.  This list doesn't replace the topics @(tsee wormhole) and @(tsee
  wormhole-eval), and their subtopics including the particularly relevant @(see
  wormhole-status).  But this list of tips might serve as a useful reminder
  when you're programming with wormholes.</p>

  <ul>

  <li>The &ldquo;function&rdquo; @(tsee wormhole) is really a macro that
  expands in raw Lisp into a call of @(tsee wormhole-eval) to set the entry
  code and then a call of @('wormhole1') to do the interactive work.  But in
  addition, the source code functions @('ev-rec'),
  @('translate11-wormhole-eval'), @('translate11-call-1'), and
  @('translate11-call') all contain special provisions for wormholes.  Do not
  think you can add features to wormholes by just changing the definition of
  @('wormhole') or @('wormhole1')!  These functions are in what we call the
  wormhole implementation nexus and there is entitled ``@('; Essay on the
  Wormhole Implementation Nexus')&rdquo; in the source file
  @('axioms.lisp').</li>

  <li>The built-in ACL2 system wormholes are protected by mechanisms in
  @('translate11-call-1') and @('translate11-call') so that code executed
  during ACL2's boot-strapping process is allowed to manipulate system
  wormholes but code executed after boot-strap cannot.  Search the source code
  for occurrences of @('*protected-system-wormhole-names*').</li>

  <li>System implementors and maintainers may be hampered by being unable to
  invoke wormhole functions on system wormholes like @('brr') or
  @('accumulated-persistence').  One way around that, e.g., to test changes to
  existing code, is to execute @('(defconst *protected-system-wormhole-names*
  nil)') after doing @('(redef+)').</li>

  <li>Users may wish to employ wormholes so they can build tools allowing the
  @(tsee state)-less exploration of their models.  But we confess that to make
  wormholes as useful to other tool developers as they are to the ACL2
  developers we will need to add some protection features (similar to those in
  the item above) to user-defined wormholes.  Ideas we have toyed with but not
  implemented include pairing a wormhole's name with various attributes such as
  a flag to prevent its use except through named interfaces, a wrapper form or
  filter that applies to every form read, translated, and evaluated by the
  @('ld') inside that wormhole, and what should happen when the wormhole is
  exited.  But these ideas are not implemented.  If you really need them, let
  us know.</li>

  <li>Each wormhole has a name, which is typically but not necessarily a
  symbol.</li>

  <li>Each wormhole has a current status.  The status is a cons whose @('car')
  is either @(':ENTER') or @(':SKIP'), and whose @('cdr') is an arbitrary ACL2
  object managed by the creator of the wormhole.  The @('car') of the status is
  called the &ldquo;entry code&rdquo;.  The @('cdr') is called the
  &ldquo;data&rdquo;.  See @(tsee wormhole-entry-code), @(tsee wormhole-data),
  and @(tsee make-wormhole-status).</li>

  <li>The status object of a wormhole named @('nm') is stored in raw Lisp in a
  part of memory inaccessible to ACL2 terms other than the ACL2 oracle (see
  @(tsee read-acl2-oracle)).  We call this the <i>persistent wormhole
  status</i> or <i>persistent-whs</i>.  If you're in raw Lisp &mdash; which you
  can reach by exiting the ACL2 loop with @(':q') or by invoking @(tsee break$)
  &mdash; you can recover the persistent-whs of the @('nm') wormhole with
  @('(cdr (assoc nm *wormhole-status-alist*))').  However, the logic-mode
  function @(tsee get-persistent-whs) takes a name and @('state') returns an
  error triple containing the persistent status.  @('Get-persistent-whs') reads
  the ACL2 oracle (see @(see read-acl2-oracle)) to get the otherwise hidden
  status of the wormhole.  In doing so it changes the state.  So if you're not
  in a context in which you have @('state') and can return a modified state,
  you can't use @('get-persistent-whs').</li>

  <li>@(tsee Wormhole-eval) gives you a way, without access to state, to set
  the persistent-whs of a named wormhole as a function of its current
  persistent-whs.  @('Wormhole-eval') takes a wormhole name, a lambda
  expression, and a term (which is functionally irrelevant), applies the lambda
  expression to the persistent-whs, stores as the new persistent-whs, and
  returns @('nil').</li>

  <li>@(tsee Wormhole) is a function that allows you to set and test the status
  of a named wormhole and if the resulting status has an entry code of
  @(':enter') you will enter a read-eval-print loop.  Wormhole has two other
  arguments, the so-called ``input'' object and the ``first form'' to execute
  if and when the loop is entered.</li>

  <li>The read-eval-print loop is managed by @(tsee ld), the same function that
  manages ACL2's top-level read-eval-print loop.  The @('wormhole') function
  allows you to specify the standard @('ld') variables (e.g., @(tsee
  ld-error-action), etc.).  One of those variables is @(tsee
  ld-keyword-aliases) which specifies the behaviors of keyword commands issued
  in the wormhole's loop.</li>

  <li>Before @('wormhole') (actually @('wormhole1')) calls @('ld') it sets
  the three important state global variables mentioned below.  Then while
  in the interactive loop:

    @({
    (@ wormhole-name) = nm

    (@ wormhole-input) = the ``input'' object supplied to wormhole

    (@ wormhole-status) = the wormhole's persistent-whs at the time of entry
    })</li>

  <li>When inside the interactive loop of the wormhole we call the value of
  @('wormhole-status') the <i>ephemeral wormhole status</i> or
  <i>ephemeral-whs</i>.  It ``disappears'' when the wormhole is exited but it
  is easy to read without changing state while inside the wormhole.</li>

  <li>The ``first form'' is very often the only form executed!  We typically
  use that form to grab the input and the status and print stuff.  Then the
  first form returns @('(value :q)').  Recall that typing @('(value :q)') to
  the ACL2 loop (i.e., to @(tsee ld)) exits the loop, which exits the wormhole.
  See the example in the documentation topic @(tsee wormhole), starting with
  "@('(wormhole 'demo')".  If the first form returns any other non-erroneous
  value triple, user input is read and evaluated.  So if your first form always
  returns @('(value :q)') you're in complete control of your wormhole &mdash;
  and if it doesn't, you're not because the next thing that happens is the
  wormhole reads and evaluates whatever the user types!</li>

  <li>The use of @('ld') to manage the read-eval-print loop means that the user
  can execute virtually any ACL2 term.  If you use @('wormhole') and allow
  input from the user, you have no control over the operations performed.</li>

  <li>If, while in the @('nm') wormhole, you execute @('(wormhole-eval nm
  ...)')  it will set the persistent-whs but not set the ephemeral-whs.
  (Recall, @('wormhole-eval') does not have access to @('state').)  This means
  that you can't trust @('(@ wormhole-status)') after a call of
  @('wormhole-eval') &mdash; or of any function that calls @('wormhole-eval')
  &mdash; from within the wormhole.</li>

  <li>This brings us to the <i>Wormhole Coherence Convention</i>.  The problem
  described in the bullet above is akin to the cache coherence problem.  Think
  of the persistent-whs stored in @('*wormhole-status-alist*') as being stored
  in a distant memory location and the ephemeral-whs stored in @('(@
  wormhole-status)') as a nearby, easily accessible cache when you're in the
  wormhole.  @('Wormhole-eval') reads and writes the persistent-whs and does
  not update the cache.  The Wormhole Coherence Convention is to keep
  persistent-whs and the ephemeral-whs equal.  Of course, the convention is
  meant to hold except in the region of code between updating the two
  locations.</li>

  <li>The wormhole programmer is responsible for maintaining the wormhole
  coherence &mdash; or not.  It's up to you.  But remember: if your wormhole
  permits user interaction, you can't prevent the execution of certain
  forms.</li>

  <li>The state global variable @('wormhole-status') is untouchable, so the
  user cannot just execute @('(assign wormhole-status new-status)') to change
  it.  But @('wormhole-status') can be changed by certain special functions
  available to the user, namely @(tsee sync-ephemeral-whs-with-persistent-whs)
  and @(tsee set-persistent-whs-and-ephemeral-whs), though these will only have
  effect after executing @(tsee wormhole-eval) or @(tsee wormhole).</li>

  <li>We have already mentioned @('wormhole-eval'), which writes to the
  persistent-whs not to the ephemeral-whs.  But the other two utilities
  mentioned above are helpful in establishing and maintaining coherence.</li>

  <li>@('(sync-ephemeral-whs-with-persistent-whs nm state)') moves the
  ``distant'' memory status into the cached status.  It returns the modified
  state.</li>

  <li>@('(set-persistent-whs-and-ephemeral-whs nm new-status state)') writes
  @('new-status') to the persistent-whs of @('nm') and, if you're in the
  wormhole @('nm'), it also updates the ephemeral-whs status.  It returns a new
  state.</li>

  <li>Using @('sync-ephemeral-whs-with-persistent-whs') and
  @('set-persistent-whs-and-ephemeral-whs') you can program your wormhole
  operations to establish and maintain coherence.  But you can't prevent the
  user from breaking it if you allow user interaction.</li>

  <li>While it may seem that @('set-persistent-whs-and-ephemeral-whs') is the
  preferred way to update the status of a wormhole, that function suffers from
  the requirement that you have to have the new status in hand when you call
  @('set-persistent-whs-and-ephemeral-whs').  So from a practical perspective
  @('set-persistent-whs-and-ephemeral-whs') is either used outside the wormhole
  to initialize the status to some standard value or is used inside the
  wormhole after having obtained the current status from the cache and
  modifying it to create the new status.</li>

  <li>Both @('sync-ephemeral-whs-with-persistent-whs') and
  @('set-persistent-whs-and-ephemeral-whs') take and return @('state') and so
  can only be used in contexts allowing that.</li>

  <li>In contrast, @('wormhole-eval') allows you to compute the new status as a
  function of the old status, <i>WITHOUT HAVING PRIOR ACCESS</i> to the old
  status and without access to @('state').  But then remember to call
  @('sync-ephemeral-whs-with-persistent-whs'), which will restore
  coherence.</li>

  <li>The most direct way to establish and maintain the wormhole coherence is
  to avoid use of fully interactive calls of @('wormhole') (i.e., make sure the
  first form executed always returns @('(value :q)')), and do all modifications
  to the wormhole status with @('wormhole-eval'), which reads and writes the
  persistent-whs.  For example, search the ACL2 sources for occurrences of
  @(''accumulated-persistence').  You'll see @('wormhole-eval') is used to
  collect all the data.  Then in @('show-accumulated-persistence-fn'),
  @('wormhole') is used to display the data and exit with @('(value :q)').</li>

  <li>But the @(tsee break-rewrite) wormhole, named @('brr'), is necessarily
  different because the whole intention is to allow interaction with the user!
  So there is special code here and there throughout ACL2 to maintain
  coherence.  We're sorry we don't provide suitable provisions for other
  users!</li>

  <li>If you're in a wormhole, all modifications to state globals during the
  execution of the commands in the read-eval-print loop will be undone when the
  loop is exited.  This cleanup is done in the raw Lisp code for
  @('wormhole1'), by evaluating the raw Lisp form held in
  @('*wormhole-cleanup-form*').  That form is destructively modified every time
  an @('f-put-global') is executed from within some wormhole.  The modification
  introduces code to undo each @('f-put-global') and restore the previous
  values.</li>

  <li>The cleanup form just mentioned contains special code for the
  @('break-rewrite') wormhole!  Look for @(''brr') in @('wormhole1') and read
  the comments.</li>

  </ul>")
other
(defxdoc wormhole-status
  :parents (wormhole)
  :short "the two senses of a wormhole's status"
  :long "<p>As noted in the discussion of @('wormhole')s, every wormhole has a
  current status, which is some ACL2 object whose shape is largely determined
  by the author of the wormhole.  That object is not stored in the ACL2 state.
  When the wormhole is entered, its status is assigned to the state global
  variable @('wormhole-status'), making it visible.  When the wormhole is
  exited, the value of @('wormhole-status') is transferred back to its
  ``hidden'' location outside of the state.  Thus, the next time it is entered
  the @('wormhole-status') is the same as it was when it was last exited.</p>

  <p>We call the ``hidden'' version of a wormhole's status the <i>persistent
  wormhole status</i> or <i>persistent-whs</i> and the version occasionally
  found in the state global @('wormhole-status') as the <i>ephemeral wormhole
  status</i> or <i>ephemeral-whs</i>.  It is helpful to think of the
  persistent-whs as the wormhole's status as stored in some distant location
  and its ephemeral-whs as an easily accessible, nearby cache.  When the two
  locations hold the same value we say the wormhole is <i>coherent</i>.</p>

  <p>The state global variable @('wormhole-status') is untouchable: you can
  read it but not directly write to it via @(tsee assign) or @(tsee
  f-put-global).  But you can write to the persistent-whs.  That is what @(tsee
  wormhole-eval) does.  So while a wormhole is coherent when you first enter it
  it can become incoherent if you use @('wormhole-eval') to change its
  persistent-whs while inside the wormhole.  And remember, the use of
  @('wormhole-eval') can be disguised via a function definition.</p>

  <p>The following script illustrates this.  First, create a wormhole named
  @('demo') whose data field is empty.  We'll use it to accumulate items
  without modifying state.  We define @('(save x)') to cons @('x') onto the
  data field of the @('demo') wormhole.  So execute these five commands at
  the top-level of ACL2.</p>

  @({
  (wormhole-eval 'demo '(lambda nil '(:enter . nil)) nil)
  (defun save (x)
    (wormhole-eval
     'demo
     '(lambda (whs)(set-wormhole-data whs (cons x (wormhole-data whs))))
     nil))
  (save 'a)
  (save 'b)
  (save 'c)
  })

  <p>Then inspect the persistent-whs of @('demo'):</p>

  @({
  ACL2 !>(get-persistent-whs 'demo state)
   (:ENTER C B A)
  })

  <p>So @('save') works as we planned.  But now let's enter the @('demo')
  wormhole.  Inside the wormhole we first inspect the ephemeral-whs (i.e.,
  @('(@ wormhole-status)'), and the persistent-whs to confirm the wormhole is
  coherent.  Then we execute @('(save 'd)') to add @('D') to the accumulator.
  Inspecting the persistent-whs shows that it worked.  But the ephemeral-whs
  did not change!  The wormhole is now incoherent, thanks to the ``disguised''
  use of @('wormhole-eval') while in the wormhole.</p>

  @({
  ACL2 !>(wormhole 'demo '(lambda (whs) whs) nil '(quote (welcome!)))

  Project-dir-alist:
  ((:SYSTEM . "/Users/moore/Desktop/v85k1/books/")).
  Type :help for help.
  Type (quit) to quit completely out of ACL2.

  Wormhole ACL2 !>(WELCOME!)
  Wormhole ACL2 !>(@ wormhole-status)
  (:ENTER C B A)
  Wormhole ACL2 !>(get-persistent-whs 'demo state)
   (:ENTER C B A)
  Wormhole ACL2 !>(save 'd)
  NIL
  Wormhole ACL2 !>(get-persistent-whs 'demo state)
   (:ENTER D C B A)
  Wormhole ACL2 !>(@ wormhole-status)
  (:ENTER C B A)
  Wormhole ACL2 !>:q
  NIL
  })

  <p>The @(':q') above exits the wormhole.  Now re-enter the wormhole and
  inspect the ephemeral-whs and persistent-whs.</p>

  @({
  ACL2 !>(wormhole 'demo '(lambda (whs) whs) nil '(quote (welcome back!)))

  Project-dir-alist:
  ((:SYSTEM . "/Users/moore/Desktop/v85k1/books/")).
  Type :help for help.
  Type (quit) to quit completely out of ACL2.

  Wormhole ACL2 !>(WELCOME BACK!)
  Wormhole ACL2 !>(@ wormhole-status)
  (:ENTER C B A)
  Wormhole ACL2 !>(get-persistent-whs 'demo state)
   (:ENTER C B A)
  Wormhole ACL2 !>(value :q)
  NIL
  })

  <p>The wormhole is coherent of course; wormholes are always coherent upon
  entry.  But notice the value of the data field!  It doesn't list @('D')!
  That happened because when we exited the wormhole, the ephemeral-whs was
  written back to the persistent-whs, and the ephemeral-whs of the incoherent
  status did not contain @('D').</p>

  <p>There are ways ensure that your wormholes remain coherent and they all
  involve using the function @(tsee sync-ephemeral-whs-with-persistent-whs),
  which does what its name says.  For example, we could have defined @('save')
  this way instead.</p>

  @({
  (defun save (x state)
    (prog2$
      (wormhole-eval
       'demo
       '(lambda (whs)(set-wormhole-data whs (cons x (wormhole-data whs))))
       nil)
      (sync-ephemeral-whs-with-persistent-whs 'demo state)))
  })

  <p>But note that we must now provide @('state') as an argument to all calls
  of @('save') and @('save') must return @('state') because @(tsee
  read-acl2-oracle) was used to reach out to the @('persistent-whs') to refresh
  the ephemeral-whs.  This means we can only call this version of @('save') in
  environments in which we have @('state') and can return @('state').</p>

  <p>Perhaps a better way preserve coherence is to keep @('save') defined in
  the earlier, @('state')-less way but to call
  @('sync-ephemeral-whs-with-persistent-whs') from within the wormhole after we
  call @('(save 'd)').  That is easy enough to do if you are in complete
  control of the @('demo') wormhole.  Recall the specification of @(tsee
  wormhole).  If the entry @('lambda') sets the @(tsee wormhole-entry-code) to
  @(':enter'), then @(tsee ld) is invoked but the first form executed by the
  resulting read-eval-print loop is the @('form') argument of @('wormhole').
  We used the @('form') argument in the script above to just print a greeting
  but it can be an arbitrary form.  If @('form') returns @('(value nil)') the
  @('ld') is exited without ever giving the user the opportunity to type and
  evaluate an arbitrary form.</p>

  <p>But if the @('demo') wormhole allows a user to type and evaluate arbitrary
  forms (including forms like @('wormhole-eval') or the @('state')-less
  @('save')), there is no way to ensure coherency.  We admit this is an
  unfortunate aspect of the current design.</p>

  <p>The simplest way to avoid such problems is to use @('wormhole-eval')
  exclusively and avoid use of the interactive read-eval-print loop provided by
  @(tsee wormhole), except loops intended for experts.  This is the approach
  taken by such system utilities as @(tsee accumulated-persistence) and @(tsee
  fc-report): @('wormhole-eval') is used to collect data and either
  @('wormhole-eval') or a non-interactive @('wormhole') is used to display
  it.</p>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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>")
other
(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-simplify :limited
                  :guard-hints (("Goal" :in-theory (theory batch1)))
                  :hints (("Goal" :in-theory (theory batch1)))
                  :loop$-recursion t
                  :measure (- i j)
                  :measure-debug t
                  :mode :logic
                  :non-executable t
                  :normalize nil
                  :otf-flg t ; the default for defun
                  :ruler-extenders :basic
                  :split-types t
                  :stobjs ($s)
                  :dfs (v1 v2)
                  :type-prescription (natp (foo x y))
                  :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).  Note that these hints apply only to guard proofs, not to the
 generation of guard proof obligations; for that, see @(see
 guard-simplification).</p>

 <p>@(':guard-simplify')<br></br>

 @('Value'): @('t') by default, which supports simplification performed while
 generating the guard proof obligation.  The value can also be @(':limited'),
 which directs ACL2 to skip such simplification that depends on which rules are
 currently @(see enable)d.  This has the same effect as the corresponding
 keyword argument to @(tsee verify-guards).  Also see @(see
 guard-simplification) and @(see guard-formula-utilities).</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>@(':')@(tsee loop$-recursion)<br></br>

 Value: this flag must be set to @('t') or @('nil'); @('nil') is the default.
 The flag must be @('t') if and only if the function being defined calls itself
 recursively from within a @(tsee loop$) body or within a @('when') or
 @('until') clause.  See @(see loop$-recursion).</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 &ldquo;Onward Through the Fog&rdquo;, to keep the
 prover from starting over when it encounters a second subgoal to be pushed for
 later proof by induction.  See @(see otf-flg)).  The default is @('t') when
 processing a @(tsee defun) or @(tsee verify-termination) event and @('nil')
 otherwise.</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.  See @(see
 induction-coarse-v-fine-grained) for a discussion of how a well-chosen
 @(':ruler-extenders') setting may improve the induction scheme suggested by a
 function.</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>@(':dfs')<br></br>

 @('Value') is either a single variable or a true list of variables.  See @(see
 df).</p>

 <p>@(':type-prescription')<br></br>

 @('Value') is either @('nil') (the default) or a formula that is suitable for
 a hypothesis-free @(':')@(tsee type-prescription) rule.  That rule must be
 appropriate for the @(':typed-term') that is the application of the defined
 function symbol to its formal parameters.  For example, a legal value for
 @(':type-prescription') in @('(defun f (x y) ...)') could be @('(or (consp (f
 x y)) (equal (f x y) y))'), but not @('(or (consp (f u v)) (equal (f u v)
 v))').  The specified formula must provide a type that is implied by the
 built-in type that is computed for the defined function.  Normally these will
 be equal, but if the value of @(':type-prescription') specifies a strictly
 weaker type than the computed built-in type then a warning will be printed
 (unless of course such warnings have been suppressed; see @(see
 set-inhibit-output-lst) and @(see set-inhibit-warnings)).  It is an error to
 supply a non-@('nil') value for @(':type-prescription') if there is no
 built-in type computed for the function.  See also @(see
 type-prescription).</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>")
other
(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)")
other
(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>")
other
(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>")
other
(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)")
other
(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)")
other
(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)")
other
(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)")
other
(defxdoc =
  :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 all occurrences of 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 Forms:
  (= x)
  (= x y)
  (= x y :kwd1 val1 ... :kwdn valn)
  (= x y atom :kwd1 val1 ... :kwdn valn)
 })

 <p>where each @(':kwdi') is one of @(':hints'), @(':otf-flg'), or @(':equiv'),
 without repetition.  In the last form, @('atom') is a non-keyword atom and no
 @('kwdi') may be @(':hints'); that atom, if supplied, is equivalent to
 @(':hints atom'), which indicates that instead of performing a proof that the
 two indicated terms (as described below) are suitably equivalent, a new such
 goal is created.</p>

 <p>If terms @('x') and @('y') are supplied, then replace @('x') by @('y')
 everywhere inside the current subterm if they are ``known'' to be equal, or
 more generally, equivalent in the sense described below.  Here ``known'' means
 the following: except in the cases that no arguments are provided or else
 @(':hints atom') is provided as described above, the prover is called as in
 the @('prove') command (using keyword arguments @(':otf') and @(':hints'), if
 supplied, where the value of @(':hints') is not an atom) to prove equivalence
 of @('x') and @('y') under the current governors and top-level hypotheses.  By
 default, this equivalence is equality; however the keyword argument
 @(':equiv') can specify a known equivalence relation.  In cases other than
 equality, substitution only takes place where justified by the equivalence
 maintained at the current subterm.</p>

 <p>For the keyword arguments, @(':equiv') defaults to @('equal') if not
 supplied or @('nil'); if it is not @('equal') (either explicitly or by
 default), then it should be the name of a known ACL2 @(see equivalence)
 relation, and substitution will only take place at subterm occurrences for
 which the @(':equiv') is among the @(see equivalence) relations being
 maintained without the use of @(see patterned-congruence)s.</p>

 <h3>Remarks on defaults</h3>

 <ul>

 <li>If there are at least two arguments, then @('x') may be the symbol
 @('&'), in any package except the keyword package, which represents the
 current subterm.</li>

 <li>The one-argument command @('(= a)') is equivalent to @('(= & a)').</li>

 <li>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').</li>

 <li>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.</li>

 <li>It is allowed to use abbreviations (see @(see acl2-pc::add-abbreviation))
 in the hints.</li>

 </ul>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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 ...) .
 })")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc contradict
  :parents (proof-builder-commands)
  :short "(macro) same as @('contrapose')"
  :long "<p>See @(see acl2-pc::contrapose).</p>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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.el') (from a suitable directory; see @(see emacs)) 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>")
other
(defxdoc 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 value of
 @('(access pc-info (@ pc-info) :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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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.el') (from a suitable directory; see @(see emacs)) 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)
  ->:
 })")
other
(defxdoc 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>")
other
(defxdoc 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').  If @('relation') is not
 @('equal') (either explicitly or by default), then substitution of @('new')
 for @('old') will only take place at occurrences for which @('relation') is
 among the @(see equivalence) relations being maintained without the use of
 @(see patterned-congruence)s.  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>")
other
(defxdoc 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>")
other
(defxdoc 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 neither @('(exit event-name ...)') nor
 @('(exit t)') will cause an exit from the interactive loop.  However, in
 that case either one 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>")
other
(defxdoc 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
 })")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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 the given index.
 That hypothesis &mdash; call it @('H') &mdash; must be of the form @('(IMPLIES
 hyp concl)').  The effect of this command is to replace @('H') by @('concl'),
 which becomes the final hypothesis.</p>

 <p>The prover must be able to prove @('concl') from the hypotheses other than
 @('H') (more precisely, to prove @('concl') after removing the hypothesis at
 the given index), 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc lemmas-used
  :parents (proof-builder-commands)
  :short "(macro)
print the runes (definitions, lemmas, ...) used"
  :long "<p>This is just an alias for @('runes').</p>

 ")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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 there have been Lisps where 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc p
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(macro)
prettyprint the current term in the usual user-level (untranslated) syntax"
  :long "@({
  Example and General Form:
  p
 })

 <p>Prettyprint the current term.  The usual user (untranslated) 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>")
other
(defxdoc 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 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 <i>*not*</i> 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>")
other
(defxdoc 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>")
other
(defxdoc pot-lst
  :parents (proof-builder-commands)
  :short "(macro)
display the linear arithmetic database based on the current context"
  :long "<p>This is a relatively advanced command.  For discussion of a related
 but more elementary command, including remarks about the utility of such a
 command, see @(see acl2-pc::type-alist).  See @(see acl2::linear-arithmetic)
 for a description of the ACL2 linear arithmetic decision procedure</p>

 @({
  Examples:
  (pot-lst nil t)   ; display linear pot-lst based on governors only (default)
  pot-lst           ; same as (pot-lst nil t) -- governors only (default)
  (pot-lst nil)     ; same as (pot-lst nil t) -- governors only (default)
  (pot-lst nil t nil nil) ; same as above
  (pot-lst nil t nil t)   ; same as above, except: raw format
  (pot-lst t t)     ; display pot-lst based on conclusion and governors
  (pot-lst t)       ; same as (pot-lst t nil) -- conclusion only
  (pot-lst nil nil) ; based on neither conclusion nor governors

  General Form:
  (pot-lst &optional concl-flg govs-flg rawp)
 })

 <p>where if @('govs-flg') is omitted then it defaults to @('(not concl-flg)'),
 and each of the other optional arguments defaults to @('nil').</p>

 <p>This command displays the linear database, also known as the linear
 <i>pot-lst</i>, that is computed from a suitable set of assumptions.  That set
 of assumptions always includes all top-level hypotheses.  By default, and when
 @('govs-flg') is supplied a non-@('nil') value, the set of assumptions
 includes all governors (which are based on surrounding if-expressions that
 must be true or false).  The negation of the current goal's top-level
 conclusion is also included in the assumptions when @('concl-flg') is supplied
 a non-@('nil') value.</p>

 <p>The computed pot-lst is based on the result of forward chaining from the
 set of assumptions as described above.  By default, that pot-lst is displayed
 in a self-explanatory way.  Here is an (admittedly contrived) example.</p>

 @({
 ACL2 !>(verify (implies (and (>= (- (nth 3 x) a) 7)
                              (< (nth 3 x) b)
                              (< c b))
                         (< (nth 3 x) d)))
 ->: promote
 ->: th
 *** Top-level hypotheses:
 1. (<= 7 (+ (NTH 3 X) (- A)))
 2. (< (NTH 3 X) B)
 3. (< C B)

 The current subterm is:
 (< (NTH 3 X) D)
 ->: pot-lst
 Current pot-lst:
 -----
 For maximal term B
 the list of polynomials is:
 ((A + 7 < B))
 -----
 For maximal term C
 the list of polynomials is:
 ((C < B))
 -----
 For maximal term (NTH '3 X)
 the list of polynomials is:
 (((NTH '3 X) < B) (A + 7 <= (NTH '3 X)))

 NIL
 ->: (pot-lst t t)
 Current pot-lst:
 -----
 For maximal term B
 the list of polynomials is:
 ((A + 7 < B))
 -----
 For maximal term C
 the list of polynomials is:
 ((C < B))
 -----
 For maximal term D
 the list of polynomials is:
 ((D < B))
 -----
 For maximal term (NTH '3 X)
 the list of polynomials is:
 (((NTH '3 X) < B) (A + 7 <= (NTH '3 X)) (D <= (NTH '3 X)))

 NIL
 ->:
 })

 <p>You can get the internal form of the pot-lst by supplying all optional
 arguments including a non-@('nil') value for @('rawp').</p>")
other
(defxdoc pp
  :parents (proof-builder-commands)
  :short "(macro)
prettyprint the current term in internal (translated) form"
  :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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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, ordered as by the command, @(tsee acl2-pc::goals).  Also see @(see
 acl2-pc::print-all-goals).</p>")
other
(defxdoc 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,
 ordered as by the command, @(tsee acl2-pc::goals).  Also see @(see
 acl2-pc::print-all-concs).</p>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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.  This includes prover calls, 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>")
other
(defxdoc 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.  This includes prover calls, 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>")
other
(defxdoc 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.  This includes prover calls, 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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''.  A call of
 @(':repeat') always ``succeeds''.</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 it may then fail, thus
 causing @(':repeat') to return.</p>")
other
(defxdoc repeat-rec
  :parents (proof-builder-commands)
  :short "(macro) auxiliary to @('repeat')"
  :long "<p>See @(see acl2-pc::repeat).</p>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc run-instr-on-goal
  :parents (proof-builder-commands)
  :short "(macro)
auxiliary to THEN"
  :long "<p>See @(see acl2-pc::then).</p>")
other
(defxdoc run-instr-on-new-goals
  :parents (proof-builder-commands)
  :short "(macro) auxiliary to @('then')"
  :long "<p>See @(see acl2-pc::then).</p>")
other
(defxdoc 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>")
other
(defxdoc 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, <see topic='@(url type-reasoning)'>type reasoning</see>
 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
 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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 it 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>")
other
(defxdoc 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 @(see acl2-pc::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>")
other
(defxdoc 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, @(see type-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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc type-alist
  :parents (proof-builder-commands)
  :short "(macro)
display the @(see type-alist) from the current context"
  :long "@({
  Examples:
  (type-alist nil t nil) ; display type-alist based on governors (default)
  type-alist             ; same as (type-alist nil t) -- governors only
  (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)   ; based on neither conclusion nor governors
  (type-alist nil t nil nil)  ; same as type-alist (default) -- governors only
  (type-alist nil t nil :raw) ; governors only, raw alist format
  (type-alist nil t nil t)    ; governors only, simple alist format

  General Form:
  (type-alist &optional concl-flg govs-flg fc-report-flg alistp)
 })

 <p>where if @('govs-flg') is omitted then it defaults to @('(not concl-flg)'),
 and each of the other optional arguments defaults 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)).  By default,
 the display is organized by type, with terms shown of each type; but when
 @('alistp') is @(':raw') then the underlying type-alist structure is shown,
 which is made more user-friendly when any other non-@('nil') value of
 @('alistp') is provided.</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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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>")
other
(defxdoc 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)
 })

 ")
other
(defxdoc 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 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>")
other
(defxdoc 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) is 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 (consp a)
     (cons (car a) (append (cdr a) b))
     b).
 })

 @({
  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>")
other
(defxdoc 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>")
other
(defxdoc bevier87
  :parents (operational-semantics-3__annotated-bibliography)
  :short "W. R. Bevier, <i>Verified Operating System Kernel</i>
  @('(ftp://ftp.cs.utexas.edu/pub/boyer/diss/bevier.pdf)'), University of Texas
  at Austin, Ph.D. dissertation, 1987.

  <br></br><br></br><b>Relevance:</b> first verified operating system and a
  component of the CLI stack"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>
  <p>The verified operating system kernel used in the CLI Verified Stack as
  reported in @(see bib::bhmy89) is described here.</p>

  <p>See the Nqthm script @('examples/bevier/kit.events').</p>")
other
(defxdoc bgm90
  :parents (operational-semantics-3__annotated-bibliography)
  :short "R. S. Boyer, M. W. Green, and J S. Moore, &ldquo;<a
  href='http://www.cs.utexas.edu/users/moore/publications/controller.pdf'>The
  Use of a Formal Simulator to Verify a Simple Real Time Control
  Program</a>&rdquo;, in W.H.J. Feijen, A.J.M. van Gasteren, D. Gries, and
  J. Misra, editors, <i>Beauty is Our Business: A Birthday Salute to Edsger
  W. Dijkstra</i>, Springer-Verlag Texts and Monographs in Computer Science,
  pp. 54-66, 1990.

  <br></br><br></br><b>Relevance:</b> operational semantics modeling a hybrid
  physical/digital system"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>We present an initial and elementary investigation of the formal
  specification and mechanical verification of programs that interact with
  environments.  We describe a formal, mechanically produced proof that a
  simple real time control program keeps a vehicle on a straightline course in
  a variable crosswind.  To formalize the specification we define a
  mathematical function which models the interaction of the program and its
  environment.  We then state and prove two theorems about this function: the
  simulated vehicle never gets farther than three units away from the intended
  course and homes to the course if the wind remains steady for at least four
  sampling intervals.</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>It is easiest to think of the problem as a one-dimensional control
  problem, e.g., a thermostat or speed control.  But the problem was posed as
  follows.  Consider the task of steering a vehicle along the x-axis with a
  crosswind along the y-axis.  The wind speed varies.  The vehicle carries a
  sensor that indicates whether the vehicle is above, on, or below the x-axis.
  The vehicle also has actuators that can adjust the sideways velocity of
  vehicle by a fixed amount.  Write, specify, and verify a control program that
  never allows the vehicle to drift too far from the x-axis and homes to the
  x-axis when the wind stays steady sufficiently long.</p>

  <p>This can be modeled as a &ldquo;clocked&rdquo; state machine, except the
  clock is a sequence of changes in wind velocity.  The &ldquo;physics&rdquo;
  is modeled extremely simply because the prover only supported natural
  numbers; but anybody who has ever written a simulator of a physical system
  will recognize it.  The proof involved defining and verifying an invariant on
  the state, under the assumption that the wind changed sufficiently
  smoothly.</p>

  <p>The work was done at SRI, probably between 1979 and 1980.  It was
  submitted for publication at that time but rejected because its formal
  approach to real-time control was too unconventional.  The reviewers
  overlooked the fact that this approach accommodated a hybrid system, where
  the control program was digital but the &ldquo;simulator&rdquo; was
  describing the physical world.  It was eventually published about a decade
  after the work was done, when the authors were invited to submit a paper to a
  volume in honor of Edsger Dijkstra.</p>

  <p>See the Nqthm script @('examples/basic/controller.events').</p>")
other
(defxdoc bhmy89
  :parents (operational-semantics-3__annotated-bibliography)
  :short "W.R. Bevier, W.A. Hunt, Jr., J S. Moore, and W.D. Young, <i>Special
   Issue on System Verification</i>, <i>Journal of Automated Reasoning</i>,
   <b>5</b>(4), pp. 409-530, 1989.

  <br></br><br></br><b>Relevance:</b> Computational Logic Inc. (CLI) Verified
  Stack &mdash; a seminal achievement in formal methods and operational
  semantics"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>
  <p>The Computational Logic, Inc (CLI) Verified Stack was
  reported in this Special Issue of the JAR.</p>

  <p>The CLI stack was composed of four verified components: a gate-level
  design for a microprocessor (by Warren Hunt), an assembler/linker/loader that
  provided an execute-only, stack-based instruction set with subroutine call
  and return (Moore), a compiler for a small subset of a programming language
  related to Pascal (Bill Young, see @(see bib::young88)), and a simple
  operating system kernel (Bill Bevier; see @(see bib::bevier87)).  All
  components were verified with Nqthm, so that a high-level program could be
  compiled, assembled, linked, loaded, and run on the gate-level machine with
  mathematical certainty that it behaved as specified by the semantics of the
  high-level programming language.  All the models just mentioned involved
  @(see operational-semantics) and proofs in the style described in here.
  Indeed, this project basically convinced the community that this style of
  semantics was practical for both execution and verification of models.</p>

  <p>The verification of the relations between each component &mdash; gates to
  machine code, machine code to assembly language, assembly language to high
  level language, operating system to assembly language &mdash; must be
  considered a &ldquo;first&rdquo; for relating practical machines of each
  kind.  To the best of our knowledge, no one had ever verified a gate-level
  implementation of an ISA for a practical microprocessor before Hunt's 1985
  work @(see bib::hunt85).  With the same caveat, no one had ever verified an
  assembler/linker/loader before Moore's 1988 Piton work (see @(see
  bib::moore96) for a history) or verified an operating system kernel for a
  practical machine before Bevier's 1987 work.  And while McCarthy and Painter
  verified (by a traditional &ldquo;hand proof&rdquo;) an expression compiler,
  which various formal methods researchers tackled in the 1970s (including
  Boyer and Moore in 1979 @(see bib::bm79), where a history of the challenge is
  sketched), both the high- and low- level machines involved in that earlier
  &ldquo;compiler&rdquo; work were trivial compared to what Young dealt with in
  1988.  The messy reality of each component was fundamentally due to the
  requirement that each layer, starting at the gates, provide sufficient
  functionality to implement the higher layers.</p>

  <p>In 1989, the &ldquo;hardware&rdquo; at the bottom of the CLI stack was a
  gate-level description of a machine called FM8502.  The FM8502 was a 32-bit
  version of Hunt's earlier 16-bit FM8501; see @(see bib::hunt85).  Hunt
  designed and verified FM8502 to make Moore's job of writing an assembler a
  little easier.  Moore, with Matt Kaufmann's help with some proofs, verified
  that the FM8502 code produced by the assembler/linker/loader implemented the
  semantics of the Piton assembly language.  But the FM8502 could not be
  fabricated because its gate-level description was not compatible with
  commercial fabrication tools, e.g., there was unrealistic fan-out.  But the
  1989 CLI Verified Stack demonstrated that it was practical to prove that a
  gate-level design implemented a given instruction set architecture (ISA) and
  that the operational semantic approach allowed the mechanized proofs of
  formal relations between different abstraction hierarchies.</p>

  <p>In 1991, Hunt and Bishop Brock designed a formal hardware description
  language (HDL) and used it to describe the FM9001 microprocessor which they
  then verified to implement its ISA; see @(see bib::hb92).  The FM9001 was
  fabricated.  In 1991, Moore retargeted the code-generators in the 1989
  assembler/linker/loader and re-verified that part of the stack, making it
  possible to port the rest of the verified stack to a fabricated, running
  machine; see @(see bib::moore96).</p>

  <p>In 1992, two other interesting projects related to Piton and FM9001 were
  completed.  Art Flatau completed the implementation and Nqthm verification of
  a second compiler, one that compiled a small subset of the Nqthm functional
  programming language into Piton (see @(see bib::flatau92)).</p>

  <p>At about the same time, Matt Wilding completed the implementation and
  verification of several real-time control programs in Piton and verified
  their functional correctness and resource bounds (instruction counts and
  stack sizes).  See @(see bib::wilding92) and @(see bib::wilding93).  One of
  the programs carried out a winning strategy for the game of Nim (if one
  exists from the given Nim starting state).</p>

  <p>Wilding wrote (@(see bib::wilding93), page 278) &ldquo;An FM9001 was
  fabricated and runs a compiled version of the Nim program. The fabricated
  FM9001 microprocessor, the Piton compiler, and the Nim program were never
  tested in a conventional manner during development or after completion. Even
  so, each worked the first time and we would have been surprised if any had
  not.&rdquo;</p>")
other
(defxdoc bh97
  :parents (operational-semantics-3__annotated-bibliography)
  :short "B. Brock and W. A. Hunt, Jr., &ldquo;<a
  href='https://ieeexplore.ieee.org/document/628846'>Formally Specifying and
  Mechanically Verifying Programs for the Motorola Complex Arithmetic
  Processor DSP</a>&rdquo;, in <i>1997 IEEE International Conference on
  Computer Design</i>, IEEE Computer Society, pp. 31-36, October, 1997.

  <br></br><br></br><b>Relevance:</b> first public announcement of the CAP
  DSP formalization (this short article was superseded by @(see bib::bh99))"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>We describe our formal specification of Motorola's Complex Arithmetic
  Processor (CAP) DSP and our subsequent use of this specification to verify
  the correctness of several DSP algorithms. We wrote the specification in
  the ACL2 logic and carried out the mechanical proofs using the ACL2
  theorem-proving system. Motorola's CAP is a super-scalar, pipelined DSP
  with seven memories and more than 20 functional units. Our formal
  specification is bit-for-bit exact, and was created by hand translating
  Motorola's drawings for the CAP. We believe that the specification
  developed is the largest of its kind, as this is the only formal
  specification of which we are aware for a complete commercial
  design. Proving the correctness of the DSP algorithms (programs) required
  proving the correctness of programs with 317-bit instructions and a
  non-interlocking execution pipeline. This Motorola DSP has a 1.8 million
  transistor implementation. This project involved both CLI and Motorola
  personnel and represents more than eight man-years of effort.</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>See the discussion of the CAP DSP project in @(see
  operational-semantics-2__other-examples).</p>")
other
(defxdoc bh99
  :parents (operational-semantics-3__annotated-bibliography)
  :short "B. Brock and W. A. Hunt, Jr., &ldquo;<a
  href='https://link.springer.com/chapter/10.1007/978-1-4471-0523-7_5#citeas'>Formal
  Analysis of the Motorola CAP DSP&rdquo;</a>, in M. Hinchey and J. Bowen,
  editors, <i>Industrial-Strength Formal Methods</i>, Springer-Verlag,
  pp. 81-115, 1999.

  <br></br><br></br><b>Relevance:</b> first industrial application of
  operational semantics with ACL2 and the first complete formal specification
  of a commercially designed microprocessor"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>We describe our formal specification of Motorola's Complex Arithmetic
  Processor (CAP) Digital Signal Processor (DSP) and our subsequent use of
  this specification in formal analyses of the CAP hardware and software. The
  CAP was designed by Motorola Government Systems and Technology Group
  (Scottsdale, Arizona), which, as a part of their business, builds and sells
  purpose-built products. The CAP is an ASIC that was designed to efficiently
  implement a number of signal processing algorithms required in digital
  communications. Motorola's CAP is a super-scalar, pipelined DSP with seven
  memories and more than 20 functional units. Motorola's specification for
  the CAP was captured using the Cadence Signal Processing (SPW) (Cadence,
  1994) toolsuite; the design is represented as a series of drawings that
  specify register files, data manipulation units, and interconnecting
  busses. We have completely specified the CAP (Gilfeather et al, 1994) using
  the formal logic ACL2 (Kaufmann and Moore, 1996). Our specification is
  executable and can be used as a simulator as well as a basis for proving
  the correctness of the CAP hardware design and CAP programs. We believe our
  specification is bit-for-bit exact with respect to the SPW specification
  produced by Motorola, and was created by hand translating Motorola's SPW
  drawings for the CAP. We have used our CAP specification to analyse the CAP
  instruction pipeline and various CAP algorithms. We believe that the
  specification developed is the largest of its kind, as this is the only
  formal specification of which we are aware for a complete commercial
  design. We believe that the use of mathematical logic for modeling and
  reasoning about hardware designs such as we have demonstrated here can
  provide assurance of circuit design correctness well beyond what is
  available from current CAD techniques.</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>See the discussion of the CAP DSP project in @(see
  operational-semantics-2__other-examples).</p>")
other
(defxdoc bkm96
  :parents (operational-semantics-3__annotated-bibliography)
  :short "B. Brock, M. Kaufmann, and J S. Moore, &ldquo;<a
   href='http://www.cs.utexas.edu/users/moore/publications/bkm96.pdf'>ACL2
   Theorems about Commercial Microprocessors</a>&rdquo;, in M. Srivas and
   A. Camilleri, editors, <i>Formal Methods in Computer-Aided Design
   (FMCAD'96)</i>, Springer-Verlag, LNCS <b>1166</b>, pp. 275-293, doi
   10.1007/BFb0031816, 1996.

  <br></br><br></br><b>Relevance:</b> early (mid-1990s) applications of ACL2 in
  industry (Motorola CAP DSP via operational semantics and the AMD K5 FDIV via
  a shallow embedding)"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>ACL2 is a mechanized mathematical logic intended for use in specifying
  and proving properties of computing machines.  In two independent projects,
  industrial engineers have collaborated with researchers at Computational
  Logic, Inc. (CLI), to use ACL2 to model and prove properties of
  state-of-the-art commercial microprocessors prior to fabrication.  In the
  first project, Motorola Inc., and CLI collaborated to specify Motorola's
  complex arithmetic processor (CAP), a single-chip, digital signal processor
  (DSP) optimized for communications signal processing.  Using the
  specifications, we proved the correctness of several CAP microcode
  programs.  The second industrial collaboration involving ACL2 was between
  Advanced Micro Devices, Inc. (AMD) and CLI.  In this work we proved the
  correctness of the kernel of the floating-point division operation on AMD's
  first Pentium-class microprocessor, the AMD5K86.  In this paper, we discuss
  ACL2 and these industrial applications, with particular attention to the
  microcode verification work.</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>This paper contains a good sketch of the Motorola CAP digital signal
  processor project, from capturing the design as an ACL2 operational model to
  proving microcode correct with respect to the model.  The paper also includes
  a timeline describing how long different phases of the project took.</p>

  <p>The paper also discusses the first use of ACL2, in 1995, to deal with
  floating-point arithmetic: verifying microcode for floating-point division on
  AMD's first Pentium-class microprocessor, the AMD5k86.  However, the
  formalization of the division microcode was not via operational semantics but
  rather a &ldquo;shallow embedding&rdquo; of the microcode into ACL2.  So
  while both the CAP project and floating-point project are of great relevance
  to the use of formal methods in industry, we have stressed the CAP work in
  this doc topic on operational semantics.  For a technical description of the
  division proof, see J S. Moore, T. Lynch, and M. Kaufmann, &ldquo;<a
  href='https://www.cs.utexas.edu/~moore/publications/divide_paper.pdf'>A
  Mechanically Checked Proof of the Correctness of the Kernel of the AMD5k86
  Floating-Point Division Program</a>&rdquo;, <i>IEEE Transactions on
  Computers</i>, <b>47</b>(9), pp. 913-926, Sep., 1998.</p>")
other
(defxdoc bm05
  :parents (operational-semantics-3__annotated-bibliography)
  :short "B. Brock and J S. Moore, &ldquo;<a
  href='https://www.cs.utexas.edu/~moore/publications/csort/main.pdf'>A
  Mechanically Checked Proof of a Comparator Sort Algorithm</a>&rdquo;, in
  M. Broy, J. Gruenbauer, D. Harel, and C. A. R. Hoare, editors,
  <i>Engineering Theories of Software Intensive Systems</i>, Springer NATO
  Science Series II, <b>195</b>, pp. 141-175, 2005.

  <br></br><br></br><b>Relevance:</b> an example of proving that the state
  transformation effected by running a CAP model on commercial microcode
  implements the high level specification"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>We describe a mechanically checked correctness proof for the comparator
  sort algorithm underlying a microcode program in a commercially designed
  digital signal processing chip.  The abstract algorithm uses an unlimited
  number of systolic comparator modules to sort a stream of data.  In
  addition to proving that the algorithm produces an ordered permutation of
  its input, we prove two theorems that are important to verifying the
  microcode implementation.  These theorems describe how positive and
  negative &ldquo;infinities&rdquo; can be streamed into the array of
  comparators to achieve certain effects.  Interesting generalizations are
  necessary in order to prove these theorems inductively.  The mechanical
  proofs were carried out with the ACL2 theorem prover.  We find these proofs
  both mathematically interesting and illustrative of the kind of mathematics
  that must be done to verify software.</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>For the 1997 ACL2 proof script see @('books/misc/csort.lisp').  The long
  delay between when the work was done (1997) and when it was published
  (2005) is due both to the understandable sensitivity of companies to permit
  publication of anything that might reveal proprietary intellectual property,
  combined with the rarity of suitable venues to describe exceedingly practical
  formal methods applications.  (Despite this phenomenon, working closely with
  industry is the only way to build tools that meet their needs.)</p>

  <p>See the discussion of the CAP DSP project in @(see
  operational-semantics-2__other-examples).</p>")
other
(defxdoc bm73
  :parents (operational-semantics-3__annotated-bibliography)
  :short "R. S. Boyer and J S. Moore, &ldquo;<a
  href='https://www.cs.utexas.edu/~moore/publications/bm-ijcai-73.pdf'>Proving
  Theorems about LISP Functions</a>&rdquo;, in <i>Proceedings of the Third
  International Joint Conference on Artificial Intelligence (IJCAI)</i>,
  Stanford University, pp. 486-493, 1973.

  <br></br><br></br><b>Relevance:</b> journal article about the Edinburgh Pure
  Lisp Theorem Prover (PLTP)"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br> <p>For a longer, journal
  version of this paper see R. S. Boyer and J S. Moore, &ldquo;<a
  href='https://www.cs.utexas.edu/~moore/publications/bm75.pdf'>Proving
  Theorems about LISP Functions</a>&rdquo;, <i>Journal of the ACM</i>,
  <b>22</b>(1), pp. 129-144, 1975.</p>

  <p>The IJCAI'73 paper was the first widely accessible description of the
  Edinburgh Pure Lisp Theorem Prover (PLTP).  The key ideas in the theorem
  prover were the use of Lisp as a logic, the reliance on recursive function
  definitions, extensive use of rewriting and symbolic evaluation, and an
  induction heuristic based on the failure of symbolic evaluation.  The system
  was fully automatic; there were no provisions for user supplied lemmas or
  hints.</p>

  <p>The &ldquo;proveall&rdquo; (regression suite) included such theorems as
  associativity of @('append'), @('reverse-reverse'), and the correctness of
  insertion sort.  The paper was hailed as a landmark in theorem proving
  because these theorems had never been proved automatically before.  But early
  critics said that proving theorems about pure Lisp was irrelevant because
  serious applications were not written in pure Lisp.  However, Boyer and Moore
  argued that Lisp was a logic with features necessary to the specification and
  proof of program properties, namely recursive definitions and mathematical
  induction.</p>

  <p><a href='https://www.cs.utexas.edu/~moore/best-ideas/pltp/index.html'>The
  PLTP Archive</a> contains a wealth of information about PLTP and its 1973
  implementation in POP-2, including the POP-2 Reference Manual, scanned OCR
  listings of the PLTP source code, listings of proof output, and modern
  reconstructions of PLTP in OCaml (by Grant Passmore) and ACL2 (by J
  Moore).</p>")
other
(defxdoc bm79
  :parents (operational-semantics-3__annotated-bibliography)
  :short "R. S. Boyer and J S. Moore, <i><a
  href='https://archive.org/details/acl_20240626'>A Computational
  Logic</a></i>, Academic Press, 1979.

  <br></br><br></br><b>Relevance:</b> implementation details of the prover that
  became Nqthm"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>This book described the &ldquo;Boyer-Moore theorem prover&rdquo; as it
  stood in 1979, when the prover was locally known as &ldquo;Thm.&rdquo; Unlike
  the Edinburgh Pure Lisp Theorem Prover (PLTP), Thm supported datatypes other
  than pairs, well-founded ordinals, a conservative definitional principle, and
  named previously proved lemmas stored as rules.  Unlike the later Nqthm, Thm
  did not support @('quote')-notation and so represented logical constants
  inefficiently.  Thm also lacked the linear-arithmetic decision procedure, and
  lacked user-supplied hints.  Of course, there were also many heuristic
  changes along the way from PLTP to Nqthm.</p>

  <p>One outstanding feature of <i>A Computational Logic</i> was noted by Boyer
  and Moore in the Preface to the First Edition of @(see bib::bm97) &ldquo;we
  know of three independent successful efforts to construct the theorem prover
  from the book.&rdquo; If you want to a good idea of how Nqthm and ACL2
  &ldquo;work,&rdquo; read this book!</p>")
other
(defxdoc bm80
  :parents (operational-semantics-3__annotated-bibliography)
  :short "R. S. Boyer and J S. Moore, &ldquo;<a
  href='https://www.cs.utexas.edu/~moore/publications/BDX930-Report-1978-81.pdf'>On
  Why It Is Impossible to Prove that the BDX930 Dispatcher Implements a
  Time-Sharing System</a>&rdquo;, in Sections 14 and 15 of P.M. Melliar-Smith,
  K. Levitt, R. Schwartz, R. Boyer, J Moore, D. Hare, R. Shostak, M. Moriconi,
  M. Green, and W.D. Elliot, <i>Investigation, Development, and Evaluation of
  Performance Proving for Fault-Tolerant Computer Final Report, covering the
  period September 1978 to June 1982</i>, SRI, July 1982.

  <br></br><br></br><b>Relevance:</b> operational semantic model of (a
  fragment) of a 1970s flight control computer"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Boyer and Moore's formalization of a subset of the instruction set of the
  Bendix BDX930 flight control computer is reported in this document.  The
  document is part of the Final Report for the Software Implemented Fault
  Tolerance (SIFT) project of SRI, sponsored by the National Aeronautics and
  Space Administration, Langley Research Center, Hampton, Va 23665.  Section 14
  explains why it was impossible to verify that the code for the SIFT
  dispatcher implemented a time-sharing system; Section 15 contains the 30 page
  listing of the operational semantics for the BDX930 fragment in question,
  written in the logic of Thm/Nqthm.  The two sections do not contain dates.
  The whole report covers the period 1978 through 1982.  Boyer and Moore left
  SRI in 1981.  The BDX930 work was probably done in 1979 or 1980 as it was
  influential in the evolution of Thm to Nqthm, as noted in @(see
  operational-semantics-5__history-etc).</p>")
other
(defxdoc bm96
  :parents (operational-semantics-3__annotated-bibliography)
  :short "R. S. Boyer and J S. Moore, &ldquo;<a
  href='https://www.cs.utexas.edu/~moore/publications/bm96.pdf'>Mechanized
  Formal Reasoning about Programs and Computing Machines</a>&rdquo;, in
  R. Veroff, editor, <i>Automated Reasoning and Its Applications: Essays in
  Honor of Larry Wos</i>, MIT Press, 1966.

  <br></br><br></br><b>Relevance:</b> the basic Nqthm/ACL2 style of operational semantics as a book chapter"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>The design of a new processor often requires the invention and use of a
  new machine-level programming language, especially when the processor is
  meant to serve some special purpose.  It is possible to specify formally the
  semantics of such a programming language so that one obtains a simulator for
  the new language from the formal semantics.  Furthermore, it is possible to
  configure some mechanical theorem provers so that they can be used directly
  to reason about the behavior of programs in the new language, permitting the
  expeditious formal modeling of the new design as well as experimentation with
  and mechanically checked proofs about new programs.  We here study a very
  simple machine-level language to illustrate how such modeling,
  experimentation, and reasoning may be done using the ACL2 automated reasoning
  system.  Of particular importance is how we control the reasoning system so
  that it can deal with the complexity of the machine being modeled.  The
  methodology we describe has been used on industrial problems and has been
  shown to scale to the complexity of state-of-the-art processors.</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>This paper describes the basic methodology used to model and reason about
  machines with ACL2: states as objects, a step function, a run function, clock
  functions for programs, lemmas to control expansion, and the basic
  methodology for specifying and verifying programs.  The vehicle for this
  explanation here is a machine almost identical to M1 and this paper covers
  essentially the same ground as the documentation topic @(see
  operational-semantics-1__simple-example).  Referring to the work described in
  @(see operational-semantics-5__history-etc) and early ACL2 work, the paper
  says</p>

  <blockquote>
  The approach we describe is essentially that used in the Nqthm and ACL2
  projects described above.  Furthermore, the Nqthm and ACL2 users above were
  taught this method of formalization via examples very similar to this one,
  primarily in our graduate class, <i>Recursion and Induction</i>, at the
  University of Texas at Austin.  That this technique scales up to languages
  that are many orders of magnitude more complicated than this one is
  demonstrated by [5, 9].  Therefore, simplicity <i>here</i> should be looked
  upon as a virtue.
  </blockquote>

  <p>While the paper does not name the machine being formalized, it was in fact
  called @('small-machine') rather than @('m1') and it goes all the way back to
  Nqthm.  Indeed, among the students who learned this methodology in
  <i>Recursion and Induction</i> in the early 1980s were Bevier, Hunt, Young,
  Flatau, and Wilding &mdash; all principals in the CLI Verified Stack work
  @(see bib::bhmy89).  See the 1991 Nqthm script
  @('examples/basic/small-machine.events'), which demonstrates that most of the
  methodology described here was developed before ACL2.  Coincidentally, it
  also shows that what we're calling @('m1') today &mdash; informally described
  as a &ldquo;toy&rdquo; Java Virtual Machine &mdash; predates the Java and the
  JVM.</p>

  <p>The ACL2 version of the @('small-machine') proof script may be found in
  the ACL2 book at
  @('https://www.cs.utexas.edu/~moore/publications/small-machine.lisp').</p>

  <p>By the way, notes for <i>Recursion and Induction</i> have been
  incorporated into ACL2's documentation.  See @(see recursion-and-induction).
  But when the course was taught by Boyer and Moore in the 1980s the notes were
  essentially just a list of conjectures to prove or disprove and the class was
  rather free-form in the sense that student participation was critical and
  often determined the kinds of problems posed in the latter part of the
  semester.  Operational semantics is not mentioned in the
  recursion-and-induction documentation.</p>")
other
(defxdoc bm97
  :parents (operational-semantics-3__annotated-bibliography)
  :short "R. S. Boyer and J S. Moore, <i><a
  href='https://drive.google.com/file/d/0B2yFYLn0Spf1TloxMjNxdzBWN1E/'> A
  Computational Logic Handbook, Second Edition</a></i>, Academic Press, New
  York, 1997.

  <br></br><br></br><b>Relevance:</b> Nqthm user's manual"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>This book is the &ldquo;final&rdquo; user's manual for Nqthm.  It was
  written about 8 years after the ACL2 project was started, by which time ACL2
  had gained a sizeable user community despite the fact that Nqthm was still
  being used by some students and industrial researchers.</p>")
other
(defxdoc boh03
  :parents (operational-semantics-3__annotated-bibliography)
  :short "R. E. Bryant and D. R. O'Hallaron, <i>Computer Systems: A
   Programmer's Perspective</i>, Prentice-Hall. First edition 2003, second
   edition 2011, third edition 2015.

  <br></br><br></br><b>Relevance:</b>one of the most popular and influential
  textbooks on modern computer systems; its relevance here is that the book
  introduced the y86."
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>For Computer Systems, Computer Organization and Architecture courses in
  CS, EE, and ECE departments. Few students studying computer science or
  computer engineering will ever have the opportunity to build a computer
  system. On the other hand, most students will be required to use and program
  computers on a near daily basis. <i>Computer Systems: A Programmer's
  Perspective</i> introduces the important and enduring concepts that underlie
  computer systems by showing how these ideas affect the correctness,
  performance, and utility of application programs. The text's hands-on
  approach (including a comprehensive set of labs) helps students understand
  the under-the-hood operation of a modern computer system and prepares them
  for future courses in systems topics such as compilers, computer
  architecture, operating systems, and networking.</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>The y86 introduced in this textbook is can be thought of as a
  &ldquo;toy&rdquo; x86 and is an excellent starting point for the
  formalization of that larger machine.</p>

  <p>The y86 has been modeled in ACL2, by Warren A. Hunt, Jr., and M. Kaufmann,
  and some programs proved correct with it.  In particular, the ACL2 book
  @('/books/models/y86/y86-basic/y86/y86.lisp') is a faithful operational
  semantic model of the 36-bit y86 described in the first edition of the
  Bryant-O'Hallaron book.</p>")
other
(defxdoc by96
  :parents (operational-semantics-3__annotated-bibliography)
  :short "R. S. Boyer and Y. Yu, &ldquo;<a
  href='https://dl.acm.org/doi/10.1145/227595.227603'>Automated Proofs of
  Object Code for a Widely Used Microprocessor</a>&rdquo;, <i>Journal of the
  ACM</i> <b>43</b>(1), pp. 166-192, January, 1996.

  <br></br><br></br><b>Relevance:</b> operational model of the Motorola 68020
  and verification of object code generated by commercial compilers"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>We have formally described a substantial subset of the MC68020, a widely
  used microprocessor built by Motorola, within the mathematical logic of the
  automated reasoning system Nqthm, a.k.a. the Boyer-Moore Theorem Prover.
  Using this formal description, we have mechanically checked the correctness
  of MC68020 object code programs for for binary search, Hoare's Quick Sort,
  twenty-one functions from the Berkeley Unix C string library, and other
  well-known algorithms.  The object code for these examples was generated
  using the Gnu C, the Verdix Ada, and the AKCL common Lisp compilers.  We have
  mechanized a mathematical theory to facilitate automated reasoning about
  object code programs.  We describe a two-stage methodology we use to do our
  proofs.</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>See also the Nqthm scripts @('examples/yu/') where you will find the
  definition of the MC68020 model and the proofs of the programs mentioned.</p>")
other
(defxdoc flatau92
  :parents (operational-semantics-3__annotated-bibliography)
  :short "A. D. Flatau <i>A verified implementation of an applicative language
  with dynamic storage allocation</i>
  @('(ftp://ftp.cs.utexas.edu/pub/boyer/diss/flatau.pdf)'), University of Texas
  at Austin, Ph.D. dissertation, 1992 (minus some appendices).

  <br></br><br></br><b>Relevance:</b> a second verified compiler hosted on
  the CLI Verified Stack"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>A compiler for a subset of the Nqthm logic and a mechanically checked
  proof of its correctness is described.  The Nqthm logic defines an
  applicative programming language very similar to McCarthy's pure Lisp [20].
  The compiler compiles programs in the Nqthm logic into the Piton assembly
  level language [23].  The correctness of the compiler is proven by showing
  that the result of executing the Piton code is the same as produced by the
  Nqthm interpreter @('V&C$').  The Nqthm logic defines several different
  abstract data types, or shells, as they are called in Nqthm.  The user can
  also define additional shells.  The definition of a shell includes the
  definition of a constructor function that returns new objects with the type
  of that shell.  These objects can become garbage, so the run-time system of
  the compiler includes a garbage collector.  The proof of the correctness of
  the compiler has not been entirely mechanically checked.  A plan for
  completing the proof is described.</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>The version of the compiler presented in the dissertation included code
  for creating new shells and a garbage collector.  But these features of the
  compiler were not fully verified at the time the dissertation was defended.
  An earlier version of the compiler dealt only with the Nqthm primitives
  @('CAR'), @('CDR'), @('CONS'), @('FALSE'), @('LISTP'), @('NLISTP'),
  @('TRUE'), @('TRUEP'), and @('IF'), as well as recursive functions.  The
  run-time of that simpler system included dynamic storage allocation (to
  allocate conses in Piton's array space).  But it did not include a garbage
  collector.  It was that simpler implementation that was mechanically
  verified.  The completion of the proofs of the full system was never
  completed.</p>

  <p>The Nqthm events for this work may be found in the @('*.events') files
  of @('examples/flatau/').</p>")
other
(defxdoc ghk13
  :parents (operational-semantics-3__annotated-bibliography)
  :short "S. Goel, W. A. Hunt, Jr., and M. Kaufmann, &ldquo;<a
  href='http://eptcs.org/content.cgi?ACL22013'>Abstract Stobjs and Their
  Application to ISA Modeling</a>&rdquo;, in R. Gamboa and J. Davis, editors,
  <i>Proceedings of ACL2 Workshop 2013</i>, Electronic Proceedings in
  Theoretical Computer Science, Volume 114, pp. 54-69, 2013.

  <br></br><br></br><b>Relevance:</b> an ACL2 feature introduced to support
  operational semantic models"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>We introduce a new ACL2 feature, the abstract stobj, and show how to apply
  it to modeling the instruction set architecture of a microprocessor. Benefits
  of abstract stobjs over traditional (&ldquo;concrete&rdquo;) stobjs can
  include faster execution, support for symbolic simulation, more efficient
  reasoning, and resilience of proof developments under modeling
  optimization.</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Aside from the specific advantages abstract stobjs (see @(tsee
  defabsstobj)) confer on ACL2 state machines, this papers illustrates how
  attention to operational semantics has influenced the development of
  ACL2.</p>")
other
(defxdoc ghkg14
  :parents (operational-semantics-3__annotated-bibliography)
  :short "S. Goel, W. A. Hunt, Jr., M. Kaufmann, and S. Ghosh, &ldquo;<a
  href='http://www.cs.utexas.edu/users/hunt/FMCAD/FMCAD14/proceedings/18_goel.pdf'>Simulation
  and Formal Verification of x86 Machine-Code Programs that Make System
  Calls</a>&rdquo;, in <i>Proceedings of Formal Methods in Computer-Aided
  Design (FMCAD'14)</i>, pp. 91-98, 2014.

  <br></br><br></br><b>Relevance:</b> modeling and verifying machine-code
  programs that exhibit non-determinism"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>We present an approach to modeling and verifying machine-code programs
  that exhibit non-determinism. Specifically, we add support for system calls
  to our formal, executable model of the user-level x86 instruction-set
  architecture (ISA). The resulting model, implemented in the ACL2
  theorem-proving system, allows both formal analysis and efficient
  simulation of x86 machine-code programs; the logical mode characterizes an
  external environment to support reasoning about programs that interact with
  an operating system, and the execution mode directly queries the underlying
  operating system to support simulation. The execution mode of our x86 model
  is validated against both its logical mode and the real machine, providing
  test-based assurance that our model faithfully represents the semantics of
  an actual x86 processor. Our framework is the first that enables mechanical
  proofs of functional correctness of user-level x86 machine-code programs
  that make system calls. We demonstrate the capabilities of our model with
  the mechanical verification of a machine-code program, produced by the GCC
  compiler, that computes the number of characters, lines, and words in an
  input stream. Such reasoning is facilitated by our libraries of ACL2 lemmas
  that allow automated proofs of a program's memory-related properties.</p>")
other
(defxdoc ghk17
  :parents (operational-semantics-3__annotated-bibliography)
  :short "S. Goel, W. A. Hunt, Jr., and M. Kaufmann, &ldquo;<a
  href='https://link.springer.com/chapter/10.1007/978-3-319-48628-4_8'>Engineering
  a Formal, Executable x86 ISA Simulator for Software Verification</a>&rdquo;,
  in M. Hinchey, J. P. Bowen, and E.-R. Olderog, editors, <i>Provably Correct
  Systems</i> Springer, pp. 173-209, 2017.

  <br></br><br></br><b>Relevance:</b> operational model of the x86 at both the
  user- and system-level and code proofs"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>Construction of a formal model of a computing system is a necessary
  practice in formal verification. The results of formal analysis can only be
  valued to the same degree as the model itself. Model development is
  error-prone, not only due to the complexity of the system being modeled,
  but also because it involves addressing disparate requirements. For
  example, a formal model should be defined using simple constructs to enable
  efficient reasoning but it should also be optimized to offer fast concrete
  simulations. Models of large computing systems are themselves large
  software systems and must be subject to rigorous validation. We describe
  our formal, executable model of the x86 instruction-set architecture; we
  use our model to reason about x86 machine-code programs. Validation of our
  x86 ISA model is done by co-simulating it regularly against a physical x86
  machine. We present design decisions made during model development to
  optimize both validation and verification, i.e., efficiency of both
  simulation and reasoning. Our engineering process provides insight into the
  development of a software verification and model animation framework from
  the points of view of accuracy, efficiency, scalability, maintainability,
  and usability.</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>See the collection of ACL2 books and files at
  @('books/projects/x86isa/').</p>

  <p>Also relevant are @(see bib::goel16) and the following earlier papers
  @(see bib::hk12), @(see bib::ghk13),and  @(see bib::ghkg14).</p>")
other
(defxdoc goel16
  :parents (operational-semantics-3__annotated-bibliography)
  :short "S. Goel, <i><a
  href='https://repositories.lib.utexas.edu/server/api/core/bitstreams/858b2f9b-5532-4b2a-bed1-fb889a265f6c/content'>Formal
  Verification of Application and System Programs Based on a Validated x86 ISA
  Model</a></i>, University of Texas at Austin, Ph.D. dissertation, 2016.

  <br></br><br></br><b>Relevance:</b> details of the x86 model"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Goel writes on page viii of the dissertation</p>

  <p>This dissertation demonstrates that formal verification of complex
  program properties can be made practical, without any loss of accuracy or
  expressiveness, by employing a machine-code analysis framework implemented
  using a mechanical theorem prover. To this end, we constructed a formal
  and executable model of the x86 Instruction-Set Architecture using the ACL2
  theorem-proving system. This model includes a specification of 400+ x86
  opcodes and architectural features like segmentation and paging. The
  model's high execution speed allows it to be validated routinely by
  performing co-simulations against a physical x86 processor &mdash; thus, formal
  analysis based on this model is reliable. We also developed a general
  framework for x86 machine-code analysis that can lower the overhead
  associated with the verification of a broad range of program properties,
  including correctness with respect to behavior, security, and resource
  requirements. We illustrate the capabilities of our framework by describing
  the verification of two application programs, population count and word
  count, and one system program, zero copy.</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Because of the concern for validating the ACL2 x86 model against x86
  hardware by various manufacturers it was important the ACL2 x86 execute
  efficiently.  When running in the application-level mode the ACL2 model
  executes at about 3.3 million x86 instructions per second (ips); in the
  system-level mode it executes at about 912,000 ips.</p>

  <p>See the collection ACL2 books and files at
  @('books/projects/x86isa/').</p>")
other
(defxdoc hb92
  :parents (operational-semantics-3__annotated-bibliography)
  :short "W. A. Hunt, Jr. and B. Brock, &ldquo;<a
  href='https://royalsocietypublishing.org/doi/abs/10.1098/rsta.1992.0024'>A
  Formal HDL and its use in the FM9001 Verification</a>&rdquo;, <i>Proceedings
  of the Royal Society</i>, North Holland, April, 1992.

  <br></br><br></br><b>Relevance:</b> a formalized hardware description language
  and the verification of a fabricated microprocessor described with it; this
  describes three foundational achievements in formal methods"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>A synchronous, hierarchical, occurrence-oriented, hardware description
  language (HDL) has been formalized with the Boyer-Moore logic. Well-formed
  HDL circuits are recognized by a predicate, and a unit-clock simulator
  defines the meaning of circuits expressed in the HDL. This HDL has been used
  to specify an implementation of the FM9001 microprocessor that has been
  mechanically proved to implement the FM9001 instruction-level
  specification. All proofs were mechanically checked using the Boyer-Moore
  theorem-proving system. The formalization of the HDL, the FM9001 user-level
  specification, and the FM9001 HDL implementation architecture specification
  required more than 700 function definitions. The mechanical proof is composed
  of thousands of theorem prover proof requests and millions of theorem prover
  inference steps.</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>The verified fabricated microprocessor described here was used in the
  final hosting of the CLI Verified Stack @(see bib::bhmy89).</p>

  <p>But aside from its importance to the Verified Stack, this paper describes
  three foundational achievements in formal methods:</p>

  <ul>

  <li>the first formal definition of a hardware description
  language (HDL),</li>

  <li>the first complete proof of a microprocessor design -- including its
  embedded test logic -- with respect to its high-level ISA specification,
  and</li>

  <li>the first (and still, only) verified microprocessor that was manufactured
  and demonstrated to function properly.</li>

  </ul>

  <p>For complete details, see the Nqthm script
  @('examples/fm9001-piton/fm9001/fm9001-replay.events').</p>")
other
(defxdoc hk12
  :parents (operational-semantics-3__annotated-bibliography)
  :short "W. A. Hunt, Jr. and M. Kaufmann, &ldquo;<a
  href='http://apps.cs.utexas.edu/tech_reports/reports/tr/TR-2075.pdf'>Towards
  a Formal Model of the x86 ISA</a>&rdquo;, University of Texas at Austin,
  Computer Science Department Technical Report TR-12-07, May, 2012.

  <br></br><br></br><b>Relevance:</b>

  a &ldquo;toy model&rdquo; of the x86, built as a warm up exercise"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>We present a preliminary formalization of a subset of the x86
  instruction set. Our model is written in the logic of the ACL2 theorem
  prover. It can be executed as a Lisp program on concrete data, which
  provides the capability to validate the model against results delivered by
  actual x86 processors. We demonstrate how bugs in our model can also be
  eliminated by using the ACL2 prover to verify guards (semantic
  preconditions) for our functions.</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>This work preceded the development of the full x86 model described in
  @(see bib::ghk13), @(see bib::ghkg14), @(see bib::goel16), and @(see
  bib::ghk17).</p>")
other
(defxdoc hkms17
  :parents (operational-semantics-3__annotated-bibliography)
  :short "W. A. Hunt, Jr., M. Kaufmann, J S. Moore, and A. Slobodova, &ldquo;<a
  href='https://royalsocietypublishing.org/doi/10.1098/rsta.2015.0399'>Industrial
  hardware and software verification with ACL2</a>&rdquo; in P. Gardner,
  P. O'Hearn, M. Gordon, G. Morrisett and F. B. Schneider, editors),
  <i>Verified Trustworthy Software Systems</i>, Philosophical Transactions A,
  Royal Society Publishing, <b>374</b>, DOI 10.1098/rsta.2015.0399, September,
  2017.

  <br></br><br></br><b>Relevance:</b> how ACL2 is used in industry, and why"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>The ACL2 theorem prover has seen sustained industrial use since the
  mid-1990s. Companies that have used ACL2 regularly include AMD, Centaur
  Technology, IBM, Intel, Kestrel Institute, Motorola/Freescale, Oracle and
  Rockwell Collins. This paper introduces ACL2 and focuses on how and why ACL2
  is used in industry. ACL2 is well-suited to its industrial application to
  numerous software and hardware systems, because it is an integrated
  programming/proof environment supporting a subset of the ANSI standard Common
  Lisp programming language. As a programming language ACL2 permits the coding
  of efficient and robust programs; as a prover ACL2 can be fully automatic but
  provides many features permitting domain-specific human-supplied guidance at
  various levels of abstraction. ACL2 specifications and models often serve as
  efficient execution engines for the modelled artefacts while permitting
  formal analysis and proof of properties. Crucially, ACL2 also provides
  support for the development and verification of other formal analysis
  tools. However, ACL2 did not find its way into industrial use merely because
  of its technical features. The core ACL2 user/development community has a
  shared vision of making mechanized verification routine when appropriate and
  has been committed to this vision for the quarter century since the
  Computational Logic, Inc., Verified Stack. The community has focused on
  demonstrating the viability of the tool by taking on industrial
  projects (often at the expense of not being able to publish much).</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>This is does not discuss operational semantics <i>per se</i> but instead
  focuses on how ACL2 is used in industry and how ACL2 gained traction in
  industrial use.  The paper discusses how ACL2 is used at Centaur Technology,
  Inc.  When a previously verified module of a microprocessor design is
  modified by the designers and checked back in to the data base, ACL2 is run
  that night to attempt to verify the modified design, &ldquo;bugs introduced
  today are detected tonight and fixed tomorrow.&rdquo; The Centaur design and
  verification teams were acquired by Intel in 2021 and ACL2 continues to be so
  used at Intel.  In addition the paper describes features of ACL2 (and of the
  ACL2 community of users) that are particularly important to industry.</p>")
other
(defxdoc hunt85
  :parents (operational-semantics-3__annotated-bibliography)
  :short "W. A. Hunt, Jr., <i>FM8501: A Verified Microprocessor</i>,
  University of Texas at Austin, Ph.D. dissertation, 1985 (also published as a
  book of the same title, Springer-Verlag LNAI 795, Heidelberg, 1994.

  <br></br><br></br><b>Relevance:</b> first microprocessor verified at the gate
  level and the bottommost component of the CLI stack"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>The precursor to the verified microprocessor used in the CLI Verified
  Stack as reported in @(see bib::bhmy89) is described here.  See the Nqthm
  script @('examples/hunt/fm8501.events')).</p>

  <p>FM8501, which had 8 registers and a 16-bit wordsize, was verified to
  implement a conventional orthogonal instruction set.  The semantics of the
  gate-level design of the FM8501 and of the instruction set were described
  operationally.  The CLI Stack was ultimately based on the FM8502, which was
  like the FM8501 except (a) the wordsize was 32-bits and (b) extra bits were
  allocated in the instruction word to permit programmer control over ALU
  condition code flags.  These changes were requested by Moore during his
  design of an assembler for the machine.  For more detail on the evolutionary
  pressure that the assembler put on the underlying machine see Section 1.5 of
  @(see bib::moore96).  Since the gate-level design of the FM8501 was
  parameterized by the word length (including the ALU), the description and
  verification of the 32-bit FM8502 was easier for Hunt than one might
  otherwise expect.  The FM8502 is described in more detail in Hunt's article
  in @(see bib::bhmy89).  Because of the way the gate-level designs of FM8501
  and FM8502 were expressed, it was impractical to fabricate either machine.
  However, see @(see bib::hb92).</p>")
other
(defxdoc kmm00a
  :parents (operational-semantics-3__annotated-bibliography)
  :short "M. Kaufmann, P. Manolios, J S. Moore, <i><a
  href='https://www.cs.utexas.edu/~moore/publications/acl2-books/car/index.html'>Computer-Aided
  Reasoning: An Approach</a></i>, Kluwer Academic Publishers, 2000.

  <br></br><br></br><b>Relevance:</b> introduction to ACL2"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>This book explains how to program in the ACL2 functional programming
  language, how that language is formalized as a logic, and how to use the
  theorem prover.  While the language and logic have acquired additional
  features in subsequent years, most new features are orthogonal to the system
  described here.  Thus, the system here describes a subset of the
  functionality of the current version of ACL2.  Probably the single most
  &ldquo;incompatible&rdquo; addition was the change of representation of the
  ordinals.  But the Errata published online in the link above explains how to
  restore the default representation assumed in the book.  Thus, this is an
  excellent beginner's introduction to how to use the system.  In contains many
  exercises and the solutions are available online.</p>")
other
(defxdoc kmm00b
  :parents (operational-semantics-3__annotated-bibliography)
  :short "M. Kaufmann, P. Manolios, J S. Moore, <i><a
  href='https://www.cs.utexas.edu/~moore/publications/acl2-books/acs/index.html'>Computer-Aided
  Reasoning: ACL2 Case Studies</a></i>, Kluwer Academic Publishers, 2000.

  <br></br><br></br><b>Relevance:</b> tutorial examples of ACL2 applications"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>This book is a companion to @(see bib::kmm00a).  It contains fourteen articles
  by ACL2 experts, explaining how they formalized and solved fourteen different
  problems.  It also includes exercises.</p>")
other
(defxdoc liu06
  :parents (operational-semantics-3__annotated-bibliography)
  :short "H. Liu, <i><a
  href='https://www.cs.utexas.edu/~moore/publications/liu-dissertation.pdf'>Formal
  Specification and Verification of a JVM and its Bytecode Verifier</a></i>,
  University of Texas at Austin, Ph.D. dissertation, 2006

  <br></br><br></br><b>Relevance:</b> most complete ACL2 model of the JVM "
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>The source files for this effort have been updated in October,
  2024 (because of changes to ACL2 since 2006) and now reside in the @(see
  community-books), in directory @('books/models/jvm/m6/').</p>

  <p>This dissertation, available at the link above, describes the
  &ldquo;M6&rdquo; model of the JVM and some important proofs about it.  It was
  the most complete model constructed in ACL2.  It executed most J2ME Java
  programs (except those with significant I/O or floating-point).  It
  supported</p>

  <ul>
  <li>all data types (except floats),</li>
  <li>multi-threading,</li>
  <li>dynamic class loading,</li>
  <li>class initialization, and</li>
  <li>synchronization via monitors.</li>
  </ul>

  <p>The M6 state includes an &ldquo;external class table&rdquo; where classes
  reside until they are loaded.  The entire Sun CLDC API library (672 methods
  in 87 classes) are translated into the external representation and are
  available for loading, constituting about 500 pages of data.  The model
  includes 21 out of 41 native APIs that appeared in Sun's CLDC API library.
  The M6 description itself is about 160 pages of ACL2.</p>

  <p>It was created with support from Sun Microsystems.</p>

  <p>On page 322, Liu describes the size of the proof effort: &ldquo;We have
  defined 2104 ACL2 functions. We proved over 4764 theorems. 196 of them are
  &ldquo;skip-proofed&rdquo;. To prove the rest of them, 971 inductions are
  necessary. The total line count of the ACL2 input is 136000. They are
  organized in 282 files. The dependency graph between the 282 ACL2 books has
  2012 edges.&rdquo;</p>

  <p><i>Note from J Moore, dissertation supervisor: The @(tsee skip-proofs) tag
  on a &ldquo;theorem&rdquo; means the conjecture is assumed rather than
  proved.  So having even one @('skip-proofs') makes it impossible to fully
  trust the results.  However, the skipped conjectures in this work are
  relatively low-level results very similar to other theorems already proved.
  Liu and I agreed that these conjectures were very probably provable and we
  were more interested in the higher-level conclusions drawn from those
  assumptions.</i></p>

  <p>An informal summary of the dissertation, by Liu, states</p>

  <p>Will a bytecode-verified Java program run safely? Why? What do we mean by
  &ldquo;safely&rdquo;?</p>

  <p>This dissertation sets out to address these questions by first building a
  precise model of the JVM and its bytecode verifier.</p>

  <p>The models are written in ACL2, for which we have computer-aided
  mechanical reasoning support.</p>

  <p>We studied how static type checking during bytecode verification can
  provide runtime type safety. We did this by examining the JVM type hierarchy
  and proving that safety conditions on operations enforced by the bytecode
  verifier can guarantee runtime type safety of the program.</p>

  <p>We also studied how the JVM type hierarchy is extended in a
  safe way by the JVM class loader that introduces new types
  into the environment.  We proved a set of theorems stating
  that the class loading process preserves the consistency of
  the JVM type hierarchy.</p>

  <p>We studied a third aspect of the JVM safety. We focused on the
  safety across method invocation and return.  We studied
  why the bytecode verifier can examine each method individually
  and provide a safety guarantee about the runtime execution of
  a program.  We note that the execution of a program is
  characterized by a stack of partially executed methods and a
  current executing method.</p>

  <p>We used the full JVM model in ACL2 to study the first two
  aspects of JVM safety.  We proved a set of theorems that
  stated the effectiveness of the bytecode verification about
  individual operations and safety of the JVM class loading.</p>

  <p>We used a simplified JVM model, which we call the small machine, to study
  the third aspect of the JVM safety.  The small machine has only one data
  type. It has branching instructions and method invocation and return
  instructions.  We proved that any small program verified by the corresponding
  simplified JVM bytecode verifier can execute safely without overflowing or
  underflowing the operand stacks.</p>")
other
(defxdoc manolios00
  :parents (operational-semantics-3__annotated-bibliography)
  :short "P. Manolios, &ldquo;<a
  href='https://dl.acm.org/doi/10.5555/646186.683220'>Correctness of Pipelined
  Machines</a>&rdquo;, in W. A. Hunt, Jr and S. D. Johnson, editors, <i>Formal
  Methods in Computer-Aided Design (FMCAD 2000)</i>, Springer-Verlag LNCS
  <b>1954</b>, Heidelberg, pp. 161-178, 2000.

  <br></br><br></br><b>Relevance:</b> an alternative approach to verifying
  operational models of a pipelined machine"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

   <p>Abstract</p>

   <p>The correctness of pipelined machines is a subject that has been studied
   extensively. Most of the recent work has used variants of the Burch and Dill
   notion of correctness. As new features are modeled, e.g., interrupts,
   new notions of correctness are developed. Given the plethora of correctness
   conditions, the question arises: what is a reasonable notion of
   correctness? We discuss the issue at length and show, by mechanical
   proof, that variants of the Burch and Dill notion of correctness are
   flawed. We propose a notion of correctness based on WEBs (Well-founded
   Equivalence Bisimulations). Briefly, our notion of correctness
   implies that the ISA (Instruction Set Architecture) and
   MA (Micro-Architecture) machines have the same observable infinite paths, up
   to stuttering. This implies that the two machines satisfy the same CTL*X
   properties and the same safety and liveness properties (up to stuttering). To
   test the utility of the idea, we use ACL2 to verify several variants of the
   simple pipelined machine described by Sawada. Our variants
   extend the basic machine by adding exceptions (to deal with overflows),
   interrupts, and fleshed-out 128-bit ALUs (one of which is described in a
   netlist language). In all cases, we prove the same final theorem. We develop
   a methodology with mechanical support that we used to verify Sawada's
   machine. The resulting proof is substantially shorter than the original and
   does not require any intermediate abstractions; in fact, given the
   definitions and some general-purpose books (collections of theorems), the
   proof is automatic. A practical and noteworthy feature of WEBs is their
   compositionality. This allows us to prove the correctness of the more
   elaborate machines in manageable stages.</p>")
other
(defxdoc mccarthy62
  :parents (operational-semantics-3__annotated-bibliography)
  :short "J. McCarthy, &ldquo;<a
  href='http://jmc.stanford.edu/articles/towards/towards.pdf'>Towards a
  mathematical science of computation</a>,&rdquo; <i>Proceedings of the
  Information Processing Cong. 62</i>, North-Holland, Munich, West Germany,
  pp. 21-28, August, 1962.

  <br></br><br></br><b>Relevance:</b> a seminal paper in the history of formal
  operational semantics"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>The pdf linked above is dated 1996, but the original paper was written in
  1962.  In a brief preface (found on the @('.html') file at the
  same site as the link above) to the 1996 paper McCarthy wrote:</p>

  <p>&ldquo;<i>Towards a Mathematical Science of Computation was given at the
  congress IFIP-62 and published in the proceedings of that conference. It
  extends the results of A Basis for a Mathematical Theory of Computation which
  was first given in 1961.</i>&rdquo;</p>

  <p>In the 1962 paper (page 19) he wrote</p>

  <p>&ldquo;The semantic description of the language must tell what the
  programs mean. The meaning of a program is its effect on the state vector in
  the case of a machine independent language, and its effect on the contents of
  memory in the case of a machine language program.&rdquo;</p>

  <p>He goes on to sketch the approach to operational semantics used most often
  in ACL2 and its predecessors.  See page 22.</p>")
other
(defxdoc mmrv06
  :parents (operational-semantics-3__annotated-bibliography)
  :short "J. Matthews, J S. Moore, S. Ray and D. Vroon, &ldquo;<a
  href='http://ece.ufl.edu/wp-content/uploads/sites/119/publications/lpar06.pdf'>
  Verification Condition Generation via Theorem Proving</a>&rdquo;, in
  <i>Proceedings of 13th International Conference on Logic for Programming,
  Artificial Intelligence, and Reasoning (LPAR 2006)</i>, LNCS <b>4246</b>,
  pp. 362-376, 2006.

  <br></br><br></br><b>Relevance:</b> how to conduct inductive assertion-style
  proofs from an operational semantics without a verification condition
  generator"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>We present a deductive method to convert (i) a formal operational
  semantics for a given machine language, and (ii) an off-the-shelf theorem
  prover, into a high assurance verification condition generator (VCG). Our
  method automatically generates verification conditions from assertions at
  join points of basic blocks of a program, analogous to those produced by a
  custom-built VCG. We show how to achieve this with a theorem prover by
  symbolic simulation on the operational semantics. Thus no separate VCG needs
  to be implemented for the target language. Furthermore, we can employ the
  full power of the theorem prover to generate and discharge the verification
  conditions.  Our method can handle both partial and total correctness, and
  recursive procedures. It is also compositional, in that the correctness of a
  subroutine needs only be proved once, rather than at each call site. The
  method has been used to verify several machine-level programs in the ACL2
  theorem prover, including the functional correctness of JVM bytecodes for a
  CBC-mode encryption algorithm.</p>")
other
(defxdoc mp67
  :parents (operational-semantics-3__annotated-bibliography)
  :short "J. McCarthy and J. Painter, &ldquo;<a
  href='http://jmc.stanford.edu/articles/mcpain/mcpain.pdf'>Correctness of a
  Compiler for Arithmetic Expressions</a>&rdquo;, <i>Proceedings of Symposia in
  Applied Mathematics</i>, <b>19</b>, American Mathematical Society, 1967.

  <br></br><br></br><b>Relevance:</b> an early (perhaps the first) compiler proof"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>This paper by gives a conventional &ldquo;hand proof&rdquo; (not a
  mechanized proof) of the correctness of a compiler for simple arithmetic
  expressions.  It demonstrates the use of an operational semantics for the
  underlying machine.</p>

  <p>This was a famous and popular challenge problem in the early history of
  formal methods.  See Chapter 17 @(see bib::bm79) for a mechanized proof a
  similar result and a discussion of the history of the mechanization of such
  compiler proofs.</p>")
other
(defxdoc moore03a
  :parents (operational-semantics-3__annotated-bibliography)
  :short "J S. Moore, &ldquo;<a
  href='https://www.cs.utexas.edu/~moore/publications/marktoberdorf-02/main_final.pdf'>Proving
  Theorems about Java and the JVM with ACL2</a>&rdquo;, in M. Broy and
  M. Pizka, editors, <i>Models, Algebras and Logic of Engineering Software</i>,
  IOS Press, Amsterdam, pp. 227-290, 2003.

  <br></br><br></br><b>Relevance:</b> M5: a JVM model with method invocation,
  classes, and threads, with some example proofs including about
  mutual-exclusion"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>This paper was the basis for a series of talks at the 2002 Marktoberdorf
  Summer School, Germany.  Among other topics, it describes the M5 JVM
  model (ACL2 script @('books/models/jvm/m5/m5.lisp')) and the use of the model
  to formalize and prove properties of a variety of JVM programs, including the
  so-called &ldquo;Apprentice Challenge&rdquo; @(see bib::mp02).  You can find
  the ACL2 scripts for these proofs on the @('books/models/jvm/m5/').  See the
  @('README') on that directory.  The M5 work here is both a fairly complicated
  operational model and a good demonstration of the &ldquo;clock&rdquo;-based
  proof methodology.</p>")
other
(defxdoc moore03b
  :parents (operational-semantics-3__annotated-bibliography)
  :short "J S. Moore, &ldquo;<a
  href='https://www.cs.utexas.edu/~moore/publications/trecia/long.pdf'>
  Inductive Assertions and Operational Semantics</a>&rdquo;, in D. Geist,
  editor, CHARME 2003,, Springer Verlag, LNCS <b>2860</b>, pp. 289-303, 2003.

  <br></br><br></br><b>Relevance:</b>The URL above points to a longer version
  of the paper presented at CHARME.  Using a subset of M5 the paper shows how
  partial symbolic evaluation of a program can be used to generate and prove
  verification conditions produced from inductive assertions"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>This paper shows how classic inductive assertions can be used in
  conjunction with an operational semantics to prove partial correctness
  properties of programs. The method imposes only the proof obligations that
  would be produced by a verification condition generator but does not require
  the definition of a verification condition generator. The paper focuses on
  iterative programs but recursive programs are briefly discussed. Assertions
  are attached to the program by defining a predicate on states. This predicate
  is then &ldquo;completed&rdquo; to an alleged invariant by the definition of
  a partial function defined in terms of the state transition function of the
  operational semantics. If this alleged invariant can be proved to be an
  invariant under the state transition function, it follows that the assertions
  are true every time they are encountered in execution and thus that the
  post-condition is true if reached from a state satisfying the
  pre-condition. But because of the manner in which the alleged invariant is
  defined, the verification conditions are sufficient to prove
  invariance. Indeed, the &ldquo;natural&rdquo; proof generates the classical
  verification conditions as subgoals. The invariant function may be thought of
  as a state-based verification condition generator for the annotated
  program. The method allows standard inductive assertion style proofs to be
  constructed directly in an operational semantics setting. The technique is
  demonstrated by proving the partial correctness of simple bytecode programs
  with respect to a pre-existing operational model of the Java Virtual
  Machine.</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>See also the paper @(see bib::rm04).</p>")
other
(defxdoc moore14
  :parents (operational-semantics-3__annotated-bibliography)
  :short "J S. Moore, &ldquo;<a
  href='https://www.cs.utexas.edu/~moore/publications/m1-is-turing-equiv.pdf'>
  Proof Pearl: Proving a Simple Von Neumann Machine Turing Complete</a>&rdquo;
  in G. Klein and R. Gamboa, editors, <i>Interactive Theorem Proving, ITP
  2014</i>, Springer LNCS <b>8558</b>, doi.org/10.1007/978-3-319-08970-6_26,
  2014.

  <br></br><br></br><b>Relevance:</b>M1 can compute anything a Turing machine
  can.  (The paper ought to be re-titled &ldquo;Proving M1 Turing
  Equivalent.&rdquo;)"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>The &ldquo;Simple Von Neumann machine&rdquo; in question is M1.  See the
  ACL2 directory @('books/models/jvm/m1/') and the @('README') file there.</p>

  <p>Abstract</p>

  <p>In this paper we sketch an ACL2-checked proof that a simple but unbounded
  Von Neumann machine model is Turing Complete, i.e., can do anything a Turing
  machine can do. The project formally revisits the roots of computer
  science. It requires re-familiarizing oneself with the definitive model of
  computation from the 1930s, dealing with a simple &ldquo;modern&rdquo;
  machine model, thinking carefully about the formal statement of an important
  theorem and the specification of both total and partial programs, writing a
  verifying compiler, including implementing an X86-like call/return protocol
  and implementing computed jumps, codifying a code proof strategy, and a
  little &ldquo;creative&rdquo; reasoning about the non-termination of two
  machines.</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>See the ACL2 book @('books/models/jvm/m1/theorems-a-and-b.lisp').</p>")
other
(defxdoc moore15
  :parents (operational-semantics-3__annotated-bibliography)
  :short "J S. Moore, &ldquo;<a
    href='https://www.cs.utexas.edu/~moore/publications/stateman.pdf'>
    Stateman: Using Metafunctions to Manage Large Terms Representing Machine
    States</a>,&rdquo; in M. Kaufmann and D. Rager, editors, <i>Proceedings of
    the 13th International Workshop on the ACL2 Theorem Prover</i>, EPTCS,
    <b>192</b>, pp. 93-109, 2015.

  <br></br><br></br><b>Relevance:</b> some ACL2 tools for managing the terms
  representing states of operational models"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>When ACL2 is used to model the operational semantics of computing
  machines, machine states are typically represented by terms recording the
  contents of the state components. When models are realistic and are stepped
  through thousands of machine cycles, these terms can grow quite large and the
  cost of simplifying them on each step grows. In this paper we describe an
  ACL2 book that uses HIDE and metafunctions to facilitate the management of
  large terms representing such states. Because the metafunctions for each
  state component updater are solely responsible for creating state
  expressions (i.e., &ldquo;writing&rdquo;) and the metafunctions for each
  state component accessor are solely responsible for extracting
  values (i.e., &ldquo;reading&rdquo;) from such state expressions, they can
  maintain their own normal form, use HIDE to prevent other parts of ACL2 from
  inspecting them, and use honsing to uniquely represent state expressions. The
  last feature makes it possible to memoize the metafunctions, which can
  improve proof performance in some machine models. This paper describes a
  general-purpose ACL2 book modeling a byte-addressed memory supporting
  &ldquo;mixed&rdquo; reads and writes. By &ldquo;mixed&rdquo; we mean that
  reads need not correspond (in address or number of bytes) with
  writes. Verified metafunctions simplify such &ldquo;read-over-write&rdquo;
  expressions while hiding the potentially large state expression. A key
  utility is a function that determines an upper bound on the value of a
  symbolic arithmetic expression, which plays a role in resolving writes to
  addresses given by symbolic expressions. We also report on a preliminary
  experiment with the book, which involves the production of states containing
  several million function calls.</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>The utility described here is available in the ACL2 book
  @('books/projects/stateman/stateman22.lisp').  See also the other files on
  that directory.  See @(see bib::moore17) for a description of the &ldquo;key
  utility,&rdquo; defined in the @('stateman22.lisp') file, that computes the
  bounds of an address.</p>")
other
(defxdoc moore17
  :parents (operational-semantics-3__annotated-bibliography)
  :short "J S. Moore, &ldquo;<a
    href='https://www.cs.utexas.edu/~moore/publications/ainni.pdf'> Computing
    Verified Machine Address Bounds during Symbolic Exploration of
    Code</a>,&rdquo; in J. Bowen, H. Langmaack and E.-R. Olderog, editors,
    <i>Provably Correct Systems</i>, Springer, pp. 151-172, 2017.

  <br></br><br></br><b>Relevance:</b> an ACL2 tool for determining whether two
  symbolic machine addresses may be equal"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>When operational semantics is used as the basis for mechanized
  verification of machine code programs it is often necessary for the theorem
  prover to determine whether one expression denoting a machine address is
  unequal to another. For example, this problem arises when trying to determine
  whether a read at the address given by expression <i>a</i> is affected by an
  earlier write at the address given by <i>b</i>. If it can be determined that
  <i>a</i> and <i>b</i> are definitely unequal, the write does not affect the
  read. Such address expressions are typically composed of &ldquo;machine
  arithmetic function symbols&rdquo; such as @('+'), @('*'), @('mod'),
  @('ash'), @('logand'), @('logxor'), etc., as well as numeric constants and
  values read from other addresses. In this paper we present an abstract
  interpreter for machine address expressions that attempts to produce a
  bounded natural number interval guaranteed to contain the value of the
  expression. The interpreter has been proved correct by the ACL2 theorem
  prover and is one of several key technologies used to do fast symbolic
  execution of machine code programs with respect to a formal operational
  semantics. We discuss the interpreter, what has been proved about it by ACL2,
  and how it is used in symbolic reasoning about machine code.</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>The utility described here is available in the ACL2 book
  @('books/projects/stateman/stateman22.lisp').</p>")
other
(defxdoc moore19
  :parents (operational-semantics-3__annotated-bibliography)
  :short "J S. Moore, &ldquo;<a
  href='https://doi.org/10.1007/s00165-019-00490-3'>Milestones from The Pure
  Lisp Theorem Prover to ACL2</a>&rdquo;, <i>Formal Aspects of Computing</i>,
  Springer, DOI https://doi.org/10.1007/s00165-019-00490-3, 2019.

  <br></br><br></br><b>Relevance:</b> how the Edinburgh Pure Lisp Theorem
  Prover (PLTP) evolved into ACL2"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

   <p>Abstract</p>

   <p>We discuss the evolutionary path from the Edinburgh Pure Lisp Theorem
   Prover of the early 1970s to its modern counterpart, A Computational Logic
   for Applicative Common Lisp, aka ACL2, which is in regular industrial
   use. Among the milestones in this evolution are the adoption of a
   first-order subset of a programming language as a logic; the analysis of
   recursive definitions to guess appropriate mathematical induction schemes;
   the use of simplification in inductive proofs; the incorporation of rewrite
   rules derived from user-suggested lemmas; the generalization of that idea to
   allow the user to affect other proof techniques soundly; the recognition
   that evaluation efficiency is paramount so that formal models can serve as
   prototypes and the logic can be used to reprogram the system; use of the
   system to prove extensions correct; the incorporation of decision
   procedures; the provision of hierarchically structured libraries of
   previously certified results to configure the prover; the provision of
   system programming features to allow verification tools to be built and
   verified within the system; the release of many verified collections of
   lemmas supporting floating point, programming languages, and hardware
   platforms; a verified &ldquo;bit-bashing&rdquo; tool exploiting verified BDD
   and checked external SAT procedures; and the provision of certain
   higher-order features within the first-order setting. As will become
   apparent, some of these milestones were suggested or even prototyped by
   users. Some additional non-technical aspects of the project are also
   critical. Among these are a devotion to soundness, good documentation,
   freely available source code, production of a system usable by industry,
   responsiveness to user needs, and a dedicated, passionate, and brilliant
   user community.</p>")
other
(defxdoc moore73
  :parents (operational-semantics-3__annotated-bibliography)
  :short "J S. Moore, &ldquo;<a
  href='http://www.era.lib.ed.ac.uk/handle/1842/2245'>Computational Logic:
  Structure Sharing and Proof of Program Properties</a>, University of
  Edinburgh, Ph.D. dissertation, 1973.

  <br></br><br></br><b>Relevance:</b> details of the Edinburgh Pure Lisp
  Theorem Prover (PLTP)"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Part II of Moore's dissertation describes the Edinburgh Pure Lisp Theorem
  Prover (PLTP) in detail.  The work was carried out jointly with Bob
  Boyer.</p>")
other
(defxdoc moore96
  :parents (operational-semantics-3__annotated-bibliography)
  :short "J S. Moore, <i>Piton:  A Mechanically Verified Assembly-Level Language</i>,
  J S. Moore, Automated Reasoning Series, Kluwer Academic Publishers, 1996.

  <br></br><br></br><b>Relevance:</b> verified assembler/linker/loader and a
  component of the CLI Verified Stack"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br> <p>The verified
  assembler/linker/loader in the final version of the CLI Stack (see @(see
  BIB::BHMY89)) is described here.  See also the 1991 Nqthm script
  @('examples/fm9001-piton/piton.events').  The Preface to the book and the
  comment at the top of the @('.events') file give a lot of history of the
  evolution of the components of the CLI Stack.</p>

  <p>Of particular interest to users who wish to verify the correct
  implementation of one programming language on top of a state machine is
  decomposition of the main theorem into &ldquo;commuting diagrams&rdquo; that
  stack various layers of abstraction between the assembly language and the
  binary image.  Among other things these layers of abstraction solve the
  problem of &ldquo;hidden resources,&rdquo; in which the lower level machine
  state has resources that are not reflected in the upper level.  For example
  at the high level, if one pushes items on the high level stack and then pops
  them off, there is no change to the stack when viewed from the high level.
  But the low level machine still records, in the region of memory dedicated to
  the stack but beyond the current top of stack, the items last pushed.
  Furthermore, those residual values can be accessed by the low level machine.
  So one has to prove that they are not.  The Piton proof dealt with this by
  imposing an intermediate abstract machine just above the low level machine
  but with an instruction set in which it is impossible to access beyond the
  top of stack.</p>")
other
(defxdoc moore99a
  :parents (operational-semantics-3__annotated-bibliography)
  :short "J S. Moore, &ldquo;<a
  href='https://www.cs.utexas.edu/~moore/publications/tjvm/main.pdf'>Proving
  Theorems about Java-like Byte Code</a>,&rdquo; in E.-R. Olderog and
  B. Steffen, editors, <i>Correct System Design -- Recent Insights and
  Advances</i>, LNCS <b>1710</b>, pp. 139-162, 1999.

  <br></br><br></br><b>Relevance:</b> M2: a JVM model similar to M1 but with
  method invocation (i.e., subroutine call)"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Recall that in @(see operational-semantics-1__simple-example) we described
  a simple machine akin to the JVM but providing only a few stack-based
  arithmetic instructions and conditional and unconditional jump instructions.
  In this paper a similar machine is formalized which provides method
  invocation and return for both static and virtual methods, and simple
  class-like instance objects with inheritance.  In the paper this machine is
  called the &ldquo;toy JVM&rdquo; or &ldquo;tjvm.&rdquo; But if we place it in
  the evolving sequence of approximations to the JVM it should be named
  &ldquo;M2.&rdquo;</p>

  <p>The ACL2 scripts providing the definition and theorems of the
  paper (but now using the name @('m2') instead of @('tjvm')) may be
  found in the ACL2 directory @('books/models/jvm/m2/').  See the @('README')
  file there.</p>")
other
(defxdoc moore99b
  :parents (operational-semantics-3__annotated-bibliography)
  :short "J S. Moore, &ldquo;<a
  href='https://www.cs.utexas.edu/~moore/publications/multi-v-uni.pdf'>A
  Mechanically Checked Proof of a Multiprocessor Result via a Uniprocessor
  View</a>&rdquo;, J S. Moore, <i>Formal Methods in System Design</i>,
  <b>14</b>(2), pp. 213-228, March, 1999.

  <br></br><br></br><b>Relevance:</b> proving a relationship between two state
  machines"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>We describe a mechanically checked correctness proof for a system of
  <i>n</i> processes, each running a simple, non-blocking counter algorithm.
  We prove that if the system runs longer than <i>5n</i> steps, the counter is
  increased.  The theorem is formalized in applicative Common Lisp and proved
  with the ACL2 theorem prover.  The value of this paper lies not so much in
  the trivial algorithm addressed as in the method used to prove it correct.
  The method allows one to reason accurately about the behavior of a
  concurrent, multiprocess system by reasoning about the sequential computation
  carried out by a selected process, against a memory that is changed
  externally.  Indeed, we prove general lemmas that allow shifting between the
  multiprocess and uniprocess views.  We prove a safety property using a
  multiprocess view, project the property to a uniprocess view, and then prove
  a global progress property via a local, sequential computation argument.  Our
  uniprocessor view is a formal compositional semantics for a shared memory
  system.</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>See the ACL2 script @('books/misc/multi-v-uni.lisp').</p>")
other
(defxdoc mp02
  :parents (operational-semantics-3__annotated-bibliography)
  :short "J S. Moore and G. Porter, &ldquo;<a
  href='https://www.cs.utexas.edu/~moore/publications/m5/apprentice.pdf'>The
  Apprentice Challenge</a>&rdquo;, <i>ACM TOPLAS</i>, <b>24</b>(3), pp. 1-24,
  May, 2002.

  <br></br><br></br><b>Relevance:</b> M5 and mutual-exclusion via monitors: an
  unbounded number of JVM threads competing for access to a shared resource"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>We describe a mechanically checked proof of a property of a small system
  of Java programs involving an unbounded number of threads and synchronization
  via monitors.  We adopt the output of the @('javac') compiler as the
  semantics and verify the system at the bytecode level under an operational
  semantics for the JVM.  We assume a sequentially consistent memory model and
  atomicity at the bytecode level.  Our operational semantics is expressed in
  ACL2, a Lisp-based logic of recursive functions.  Our proofs are checked with
  the ACL2 theorem prover.  The proof involves reasoning about arithmetic,
  infinite loops, the creation and modification of instance objects in the
  heap, including threads, the inheritance of fields from superclasses, pointer
  chasing and smashing, the invocation of instance methods (and the concomitant
  dynamic method resolution), use of the @('start') method on thread objects,
  the use of monitors to attain synchronization between threads, and
  consideration of all possible interleavings (at the bytecode level) over an
  unbounded number of threads.  Readers familiar with monitor-based proofs of
  mutual-exclusion will recognize our proof as fairly classical.  The novelty
  here comes from (i) the complexity of the individual operations on the
  abstract machine, (ii) the dependencies between Java threads, heap objects,
  and synchronization, (iii) the bytecode-level interleaving, (iv) the
  unbounded number of threads, (v) the presence in the heap of incompletely
  initialized threads and other objects, and (vi) the proof engineering
  permitting automatic mechanical verification of code-level theorems.  We
  discuss these issues.  The problem posed here is also put forth as a
  benchmark against which to measure other approaches to formally proving
  properties of multi-threaded Java programs.</p>")
other
(defxdoc plotkin04a
  :parents (operational-semantics-3__annotated-bibliography)
  :short "G. D. Plotkin, &ldquo;<a
  href='https://homepages.inf.ed.ac.uk/gdp/publications/sos_jlap.pdf'> A
  Structural Approach to Operational Semantics</a>&rdquo;, Computer Science
  Department, Aarhus University, Denmark, DAIMI FN-19, 1981 (reprised in a 2004
  submission to the <i>The Journal of Logic and Algebraic Programming</i>).

  <br></br><br></br><b>Relevance:</b> Plotkin's introduction of the term
  &ldquo;structural operational semantics&rdquo;"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>In the introduction to this historically important &ldquo;Aahus
  note&rdquo; Plotkin wrote:</p>

  <p>1.1 Introduction</p>

  <p>It is the purpose of these notes to develop a simple and direct method for
  specifying the semantics of programming languages. Very little is required in
  the way of mathematical background; all that will be involved is
  &ldquo;symbol-pushing&rdquo; of one kind or another of the sort which will
  already be familiar to readers with experience of either the non-numerical
  aspects of programming languages or else formal deductive systems of the kind
  employed in mathematical logic.</p>

  <p>Apart from a simple kind of mathematics the method is intended to produce
  concise comprehensible semantic definitions. Indeed the method is even
  intended as a direct formalisation of (many aspects of) the usual informal
  natural language descriptions. I should really confess here that while I have
  some experience what has been expressed above is rather a pious hope than a
  statement of fact. I would therefore be most grateful to readers for their
  comments and particularly their criticisms.</p>

  <p>I will follow the approach to programming languages taken by such authors
  as Gordon [Gor] and Tennent [Ten] considering the main syntactic classes
  &mdash; expressions, commands and declarations &mdash; and the various
  features found in each. The linguistic approach is that developed by the
  Scott-Strachey school (together with Landin and McCarthy and others) but
  within an operational rather than a denotational framework. These notes
  should be considered as an attempt at showing the feasibility of such an
  approach. Apart from various inadequacies of the treatment as presented many
  topics of importance are omitted. These include data structures and data
  types; various forms of control structure from jumps to exceptions and
  coroutines; concurrency including semaphores, monitors and communicating
  process.</p>")
other
(defxdoc plotkin04b
  :parents (operational-semantics-3__annotated-bibliography)
  :short " G. D. Plotkin, &ldquo;<a
  href='https://www.sciencedirect.com/science/article/pii/S1567832604000268'>
  The origins of structural operational semantics</a>&rdquo;, <i>The Journal of
  Logic and Algebraic Programming</i>, <b>60</b> and <b>61</b>, pp. 3-15, July
  and December 2004.

  <br></br><br></br><b>Relevance:</b> an interesting historical account of the
  most popular (non-ACL2) approach to operational semantics"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>The term &ldquo;structural Operational Semantics&rdquo; was introduced by
  Gordon Plotkin in technical note DAIMI FN-19, Computer Science Department,
  Aarhus University, 1981.  That sense of &ldquo;operational semantics&rdquo;
  is probably the most popular today and the literature has grown enormously
  since the original note.  For that reason, we cite this &ldquo;origins&rdquo;
  paper because it was published in a two volume special issue of <i>The
  Journal of Logic and Algebraic Programming</i>.  Furthermore, the original
  1981 &ldquo;Aarhus note&rdquo; is included in that issue, and that special
  issue can be downloaded in full from this citation.</p>

  <p>The approach to operational semantics most widely used in the ACL2
  community is different from structural operational semantics.  Plotkin
  formalized machines operationally but as inference rules (reminiscent of
  Hoare logic), whereas in ACL2 the logic is fixed &mdash; it is the logic of
  the ACL2 theorem prover &mdash; and in ACL2 the theory is extended via
  conservative definitions to describe the operation of the machines in
  question.</p>

  <p>In this origins paper, Plotkin writes</p>

  <blockquote>

  <p>&ldquo;The IBM Vienna school [41,42] were interested in specifying real
  programming languages, and, in particular, worked on an abstract interpreting
  machine for PL/I using VDL, their Vienna Definition Language; they were
  influenced by the ideas of McCarthy, Landin and Elgot [18].</p>

  <p>I remember attending a seminar at Edinburgh where the intricacies of their
  PL/I abstract machine were explained. The states of these machines are tuples
  of various kinds of complex trees and there is also a stack of environments;
  the transition rules involve much tree traversal to access syntactical
  control points, handle jumps, and to manage concurrency. I recall not much
  liking this way of doing operational semantics. It seemed far too complex,
  burying essential semantical ideas in masses of detail; further, the machine
  states were too big. The lesson I took from this was that abstract
  interpreting machines do not scale up well when used as a human-oriented
  method of specification for real languages (but see below for further
  comment).&rdquo;</p>

  </blockquote>

  <p>There is no doubt that interpretive operational semantics for commercial
  microprocessors is enormously complicated and much of that complexity is
  buried in data structures, but we in the ACL2 community tend to regard that
  as an unavoidable consequence of how the machines are designed and the fact
  that the structure of the designs manifest themselves in behaviors that users
  see.  Would a structural operational semantics for the system-level view of
  x86 be less complex than the ACL2 x86 model described in @(see bib::goel16)?
  We also agree with Plotkin's observation that the interpretive approach does
  not scale well <i>when used as a human-oriented method of specification for
  real languages</i>.  However, our focus is on <i>mechanized</i> reasoning
  about machines and we are optimistic that mechanization can manage the
  complexity.  Furthermore, we believe the examples discussed in @(see
  operational-semantics-2__other-examples) support our optimism.  Of course, as
  noted in @(see operational-semantics-1__simple-example), the ACL2 user is
  responsible for configuring ACL2's prover to manage the complexity but the
  evidence is that expert users are capable of doing that, exploiting such ACL2
  features as rewrite rules, metafunctions, enabling and disabling, pragmas for
  controlling rules, and hints (including computed hints).</p>")
other
(defxdoc rhmm07
  :parents (operational-semantics-3__annotated-bibliography)
  :short "S. Ray, W. A. Hunt, Jr., J. Matthews, and J S. Moore, `<a
  href='https://link.springer.com/article/10.1007/s10817-008-9098-1'>A
  Mechanical Analysis of Program Verification Strategies</a>,&rdquo; <i>Journal
  of Automated Reasoning</i>, <b>40</b>(4), pp. 245-269, May, 2008.

  <br></br><br></br><b>Relevance:</b> stepwise invariants, clock functions, and
  inductive assertion proof styles are all equivalent"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>We analyze three proof strategies commonly used in deductive verification
  of deterministic sequential programs formalized with operational
  semantics. The strategies are (i) stepwise invariants, (ii) clock functions,
  and (iii) inductive assertions. We show how to formalize the strategies in
  the logic of the ACL2 theorem prover. Based on our formalization, we prove
  that each strategy is both sound and complete. The completeness result
  implies that given any proof of correctness of a sequential program one can
  derive a proof in each of the above strategies. The soundness and
  completeness theorems have been mechanically checked with ACL2.</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>See also @(see bib::rm04).</p>")
other
(defxdoc rm04
  :parents (operational-semantics-3__annotated-bibliography)
  :short "S. Ray and J S. Moore, &ldquo;<a
  href='https://www.ece.ufl.edu/wp-content/uploads/sites/119/publications/fmcad04.pdf'>Proof
  Styles in Operational Semantics</a>,&rdquo; in A. J. Hu and A. K. Martin,
  editors, <i>Formal Methods in Computer-Aided Design (FMCAD-2004)</i>,
  Springer, LNCS <b>3312</b>, pp. 67-81, 2004.

  <br></br><br></br><b>Relevance:</b> ACL2 tools for transforming inductive
  assertion-style proofs to clock function style and vice versa"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>We relate two well-studied methodologies in deductive verification of
  operationally modeled sequential programs, namely the use of inductive
  invariants and clock functions. We show that the two methodologies are
  equivalent and one can mechanically transform a proof of a program in one
  methodology to a proof in the other. Both partial and total correctness are
  considered. This mechanical transformation is compositional; different
  parts of a program can be verified using different methodologies to achieve a
  complete proof of the entire program. The equivalence theorems have been
  mechanically checked by the ACL2 theorem prover and we implement automatic
  tools to carry out the transformation between the two methodologies in
  ACL2.</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>See also the files by S. Ray on the ACL2 directory
  @('books/proofstyles/').</p>")
other
(defxdoc sawada00
  :parents (operational-semantics-3__annotated-bibliography)
  :short "J. Sawada, &ldquo;Verification of a Simple Pipelined Machine
  Model,&rdquo; in M. Kaufmann, P. Manolios, J S. Moore, editors,
  <i>Computer-Aided Reasoning: ACL2 Case Studies</i>, Kluwer Academic
  Publishers, Chapter 9, pp. 137-150, 2000. (See also @(see pubs::pubs-books).)

  <br></br><br></br><b>Relevance:</b> operational model of a pipelined machine
  and its verification"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>The difficulty of pipelined machine verification derives from the fact
  that there is a complex time-abstraction between the pipelined implementation
  and its specification which executes instructions sequentially.  To study
  this problem, we define a simple three-stage pipelined machine in ACL2.  We
  prove that this pipelined machine returns the same result as its
  specification machine.  In order to ease the proof, we define an intermediate
  abstraction called MAETT.  This abstraction models the behavior of
  instructions in the pipelined architecture, and it allows us to define
  directly and verify invariant conditions about executed instructions.  The
  author used a similar approach to verify a more realistic pipelined machine.
  This chapter serves as an introduction to the verification of pipelined
  machines.</p>")
other
(defxdoc sh98
  :parents (operational-semantics-3__annotated-bibliography)
  :short "J. Sawada and W. A. Hunt, Jr, &ldquo;<a
  href='https://link.springer.com/chapter/10.1007/BFb0028740'>Processor
  Verification with Precise Exceptions and Speculative Execution</a>&rdquo;, in
  A. J. Hu and M. Y. Vardi, editors, <i>Computer Aided Verification, (CAV
  '98)</i>, Springer-Verlag LNCS <b>1427</b>, Heidelberg, pp. 135-146, 1998.

  <br></br><br></br><b>Relevance:</b> proof method for dealing with exceptions
  and speculative execution"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>We describe a framework for verifying a pipelined microprocessor whose
  implementation contains precise exceptions, external interrupts, and
  speculative execution. We present our correctness criterion which compares
  the state transitions of pipelined and non-pipelined machines in presence of
  external interrupts. To perform the verification, we created a table-based
  model of pipeline execution. This model records committed and in-flight
  instructions as performed by the microarchitecture. Given that certain
  requirements are met by this table-based model, we have mechanically verified
  our correctness criterion using the ACL2 theorem prover.</p>")
other
(defxdoc wilding92
  :parents (operational-semantics-3__annotated-bibliography)
  :short "M. M. Wilding, <i>Machine-checked real-time system verification</i>
  @('(ftp://ftp.cs.utexas.edu/pub/boyer/diss/wilding.pdf)'), University of
  Texas at Austin, Ph.D. dissertation, 1996.

  <br></br><br></br><b>Relevance:</b> a non-trivial applications program on the CLI Verified Stack"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>In the introduction to this dissertation, the author writes:</p>

  <p>&ldquo;The complexity and importance of real-time systems makes their formalization
  and verification crucial.  We ensure proper real-time system behavior in several ways
  through mathematical proof.  We check proofs using Nqthm, a mechanical proof system
  also known as the Boyer-Moore theorem prover.</p>

  <p>...</p>

  <p>We verify a high-level language application that, using a proved compiler
  and microprocessor design, assures the optimality and timely behavior of an
  application.  The verified program uses a clever algorithm to meet its
  specification and a method for structuring proofs allows large verified
  programs to be developed.  An interpreter-based language semantics allows
  reliable execution behavior reasoning, including reasoning about
  timing.&rdquo;</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>The dissertation deals with several programs written in the Piton assembly
  language (@(see bib::moore96)) for the FM9001 (@(see bib::hb92)).  In
  addition to establishing functional correctness, the proofs ensure that the Piton
  images fit in the space provided by the fabricated FM9001, provide upper
  bounds on the instruction counts, and the sizes of both the control stack and
  the temporary stack implemented by Piton on the FM9001.  See also @(see
  bib::wilding93) for a discussion of one of these programs, namely one that
  implements a winning strategy for the game of Nim.</p>

  <p>See the Nqthm scripts by downloading and extracting the @('*.events')
  files from
  @('ftp://ftp.cs.utexas.edu/pub/boyer/diss/wilding-diss-events.tar').</p>")
other
(defxdoc wilding93
  :parents (operational-semantics-3__annotated-bibliography)
  :short "M. M. Wilding, &ldquo;<a
        href='https://link.springer.com/content/pdf/10.1007/3-540-56922-7_22'>A
        Mechanically Verified Application for a Mechanically Verified
        Environment</a>, in C. Courcoubetis, editor, <i>Proceedings of
        Computer-Aided Verification -- CAV '93</i>, Springer-Verlag, LNCS
        <b>697</b>, Heidelberg, pp. 268-279, DOI:10.1007/3-540-56922-7_22,
        1993.

   <br></br><br></br><b>Relevance:</b> functional correctness and resource
   utilization of a Nim-playing program on the CLI Verified Stack"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>We have developed a verified application proved to be both effective and
  efficient. The application generates moves in the puzzle-game Nim and is
  coded in Piton, a language with a formal semantics and a compiler verified
  to preserve its semantics on the underlying machine. The Piton compiler is
  targeted to the FM9001, a recently fabricated verified microprocessor. The
  Nim program correctness proof makes use of the language semantics that the
  compiler is proved to implement. Like the Piton compiler proof and FM9001
  design proof, the Nim correctness proof is generated using Nqthm, a proof
  system sometimes known as the Boyer-Moore theorem prover.</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>The paper proves that a Piton program constructed by the author implements
  a winning strategy (if one exists for a given starting state) of the game of
  Nim.  In addition, he proved a bound on the number of instructions executed
  on each move as well as bounds on the sizes of both the control stack and the
  temporary stack.</p>

  <p>In the conclusion of the paper (page 278) the author writes</p>

  <p>&ldquo;Mechanical verification of programs in this manner is time-consuming and
  difficult. Nevertheless, and quite remarkably, the experience of building the
  Nim program suggests that development time scales linearly with program
  length. Once a Piton subroutine has been proved correct, a call to this
  subroutine can be reasoned about as easily as any basic Piton statement.</p>

  <p>...</p>

  <p>An FM9001 was fabricated and runs a compiled version of the Nim
  program. The fabricated FM9001 microprocessor, the Piton compiler, and the
  Nim program were never tested in a conventional manner during development or
  after completion. Even so, each worked the first time and we would have been
  surprised if any had not.&rdquo;</p>")
other
(defxdoc young88
  :parents (operational-semantics-3__annotated-bibliography)
  :short "W. D. Young, <i>A Verified Code Generator for a Subset of Gypsy</i>
  @('(ftp://ftp.cs.utexas.edu/pub/boyer/diss/young.pdf)'), University of Texas
  at Austin, Ph.D. dissertation, 1988.

  <br></br><br></br><b>Relevance:</b> a verified compiler (from a small
  Pascal-like subset to an assembly language) and a component of the CLI
  Verified Stack"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>
  <p>The verified compiler used in the CLI Verified Stack as
  reported in @(see bib::bhmy89) is described here.  By the way, we could not
  find the original Nqthm script for this effort, but the complete script is included in
  Appendix B of the linked pdf file above, pages 206-860.</p>")
other
(defxdoc yu92
  :parents (operational-semantics-3__annotated-bibliography)
  :short "Y. Yu, <i>Automated proofs of object code for a widely used
  microprocessor</i> @('(ftp://ftp.cs.utexas.edu/pub/boyer/diss/yu.pdf)'),
  University of Texas at Austin, Ph.D. dissertation, 1992.

  <br></br><br></br><b>Relevance:</b> details of the operational model of the
  Motorola 68020"
  :long "<br></br>&mdash;&mdash;&mdash;<br></br>

  <p>Abstract</p>

  <p>Computing devices can be specified and studied mathematically.  Formal
  specification of computing devices has many advantages &mdash; it provides a
  precise characterization of the computational model and allows for
  mathematical reasoning about models of the computing devices and programs
  executed on them.  While there has been a large body of research on program
  proving, work has almost exclusively focused on programs written in high
  level programming languages.  This thesis addresses the very important but
  largely ignored problem of machine code program proving.  In this thesis we
  have formally described a substantial subset of the MC68020, a widely used
  microprocessor built by Motorola, within the mathematical logic of the
  automated reasoning system Nqthm, a.k.a. the Boyer-Moore Theorem Proving
  System.  Based on this formal model, we have mechanized a mathematical theory
  to facilitate automated reasoning about object code programs.  We then have
  mechanically checked the correctness of MC68020 object code programs for
  binary search, Hoare's Quick Sort, the Berkeley Unix C string library, and
  other well-known algorithms.  The object code for these examples were
  generated using the Gnu C, the Verdix Ada, and the AKCL common Lisp
  compilers.</p>

  <br></br>&mdash;&mdash;&mdash;<br></br>

  <p>See also the Nqthm scripts @('examples/yu/') where you will find the
  definition of the MC68020 model and the proofs of the programs mentioned.</p>")
other
(defpointer &allow-other-keys macro-args)
other
(defpointer &body macro-args)
other
(defpointer &key macro-args)
other
(defpointer &optional macro-args)
other
(defpointer &rest macro-args)
other
(defpointer &whole macro-args)
other
(defpointer abstract-stobj defabsstobj)
other
(defpointer accumulated-persistence-oops
  accumulated-persistence)
other
(defpointer acl2-unwind-protect system-utilities)
other
(defpointer acl2p parallelism)
other
(defpointer acl2r real)
other
(defpointer acl2s acl2-sedan)
other
(defpointer add-ld-keyword-alias ld-keyword-aliases)
other
(defpointer add-ld-keyword-alias! ld-keyword-aliases)
other
(defpointer add-suffix system-utilities)
other
(defpointer add-suffix-to-fn system-utilities)
other
(defpointer add-to-set-eq add-to-set)
other
(defpointer add-to-set-eql add-to-set)
other
(defpointer add-to-set-equal add-to-set)
other
(defpointer adjust-ld-history ld-history)
other
(defpointer all-attachments system-utilities)
other
(defpointer all-calls system-utilities)
other
(defpointer all-fnnames system-utilities)
other
(defpointer all-fnnames-lst system-utilities)
other
(defpointer all-fnnames1 system-utilities)
other
(defpointer all-vars system-utilities)
other
(defpointer always$ loop$)
other
(defpointer always$+ loop$)
other
(defpointer append$ loop$)
other
(defpointer append$+ loop$)
other
(defpointer apropos finding-documentation)
other
(defpointer arglistp system-utilities)
other
(defpointer array arrays)
other
(defpointer assertions errors)
other
(defpointer assoc-eq assoc)
other
(defpointer assoc-equal assoc)
other
(defpointer auto-instance defthm<w)
other
(defpointer backchain-limit-rw hints t)
other
(defpointer backtrack hints t)
other
(defpointer bibliography publications)
other
(defpointer body system-utilities)
other
(defpointer book-makefiles books-certification)
other
(defpointer by hints t)
other
(defpointer cases hints t)
other
(defpointer ccl-updates ccl-installation)
other
(defpointer certifiable certify-book)
other
(defpointer certify-book-failure certify-book-debug)
other
(defpointer certifying-books books-certification)
other
(defpointer check-invariant-risk set-check-invariant-risk)
other
(defpointer close-input-channel io)
other
(defpointer close-output-channel io)
other
(defpointer check-sum checksum)
other
(defpointer coherence wormhole-status)
other
(defpointer collect$ loop$)
other
(defpointer collect$+ loop$)
other
(defpointer comma backquote)
other
(defpointer comma-atsign backquote)
other
(defpointer community-book community-books)
other
(defpointer computed-hint computed-hints)
other
(defpointer conjoin system-utilities)
other
(defpointer conjoin2 system-utilities)
other
(defpointer cons-term system-utilities)
other
(defpointer cons-term* system-utilities)
other
(defpointer context ctx)
other
(defpointer cw-gstack-for-subterm* with-brr-data)
other
(defpointer cw-gstack-for-subterm with-brr-data)
other
(defpointer cw-gstack-for-term* with-brr-data)
other
(defpointer cw-gstack-for-term with-brr-data)
other
(defpointer d< l<)
other
(defpointer declaration declare)
other
(defpointer default-state-vars system-utilities)
other
(defpointer default-verify-guards-eagerness
  set-verify-guards-eagerness)
other
(defpointer defined-constant system-utilities)
other
(defpointer disjoin system-utilities)
other
(defpointer disjoin2 system-utilities)
other
(defpointer do-not-induct hints t)
other
(defpointer double-float df)
other
(defpointer doublet-listp system-utilities)
other
(defpointer dynamically-monitor-rewrites dmr)
other
(defpointer dumb-negate-lit system-utilities)
other
(defpointer dumb-occur system-utilities)
other
(defpointer dumb-occur-var system-utilities)
other
(defpointer enabled-numep system-utilities)
other
(defpointer enabled-runep system-utilities)
other
(defpointer ephemeral-whs wormhole-status)
other
(defpointer er-cmp context-message-pair)
other
(defpointer er-let* programming-with-state)
other
(defpointer er-let*-cmp context-message-pair)
other
(defpointer er-progn-cmp context-message-pair)
other
(defpointer error hints t)
other
(defpointer ev$-list apply$)
other
(defpointer event events)
other
(defpointer event-data saving-event-data)
other
(defpointer execution evaluation)
other
(defpointer expand hints t)
other
(defpointer extended-syntaxp syntaxp)
other
(defpointer external-format character-encoding)
other
(defpointer fake-rune rune)
other
(defpointer fargn system-utilities)
other
(defpointer fargs system-utilities)
other
(defpointer fast-alist fast-alists)
other
(defpointer fast-alist-discipline slow-alist-warning)
other
(defpointer fcons-term system-utilities)
other
(defpointer fcons-term* system-utilities)
other
(defpointer fdefun-mode system-utilities)
other
(defpointer ffn-symb system-utilities)
other
(defpointer ffn-symb-p system-utilities)
other
(defpointer ffnnamep system-utilities)
other
(defpointer ffnnamep-lst system-utilities)
other
(defpointer first-keyword system-utilities)
other
(defpointer first-n-ac take)
other
(defpointer fix-pkg system-utilities)
other
(defpointer flambda-applicationp system-utilities)
other
(defpointer flambdap system-utilities)
other
(defpointer flatten-ands-in-lit system-utilities)
other
(defpointer fms!-to-string printing-to-strings)
other
(defpointer fms-to-string printing-to-strings)
other
(defpointer fmt!-to-string printing-to-strings)
other
(defpointer fmt-hard-right-margin set-fmt-hard-right-margin)
other
(defpointer fmt-soft-right-margin set-fmt-hard-right-margin)
other
(defpointer fmt-to-string printing-to-strings)
other
(defpointer fmt1!-to-string printing-to-strings)
other
(defpointer fmt1-to-string printing-to-strings)
other
(defpointer fmx!-cw fmx-cw)
other
(defpointer fn-rune-nume system-utilities)
other
(defpointer fn-symb system-utilities)
other
(defpointer fncall-term meta-extract)
other
(defpointer forced force)
other
(defpointer formals system-utilities)
other
(defpointer fquotep system-utilities)
other
(defpointer fsubcor-var system-utilities)
other
(defpointer function-symbolp system-utilities)
other
(defpointer gcs get-command-sequence)
other
(defpointer genvar system-utilities)
other
(defpointer get-brr-local system-utilities)
other
(defpointer get-check-invariant-risk
  set-check-invariant-risk)
other
(defpointer get-defun-event system-utilities)
other
(defpointer get-event system-utilities)
other
(defpointer get-in-theory-redundant-okp
  set-in-theory-redundant-okp)
other
(defpointer get-output-stream-string$ io)
other
(defpointer get-register-invariant-risk
  set-register-invariant-risk)
other
(defpointer get-serialize-character
  with-serialize-character)
other
(defpointer get-skipped-proofs-p system-utilities)
other
(defpointer getting-started acl2-tutorial)
other
(defpointer guards guard)
other
(defpointer guard-checking set-guard-checking)
other
(defpointer guard-hints xargs t)
other
(defpointer guard-msg-table set-guard-msg)
other
(defpointer guard-holder guard-holders)
other
(defpointer hands-off hints t)
other
(defpointer hash-tables defstobj)
other
(defpointer if-intro splitter)
other
(defpointer ignorable declare)
other
(defpointer ignore declare)
other
(defpointer ilks ilk)
other
(defpointer immed-forced splitter)
other
(defpointer implicate system-utilities)
other
(defpointer induct hints t)
other
(defpointer inline defun-inline)
other
(defpointer interrupts abort-soft)
other
(defpointer intersection-eq intersection$)
other
(defpointer intersection-equal intersection$)
other
(defpointer intersectp-eq intersectp)
other
(defpointer intersectp-equal intersectp)
other
(defpointer io? system-utilities)
other
(defpointer iprint set-iprint)
other
(defpointer iprinting set-iprint)
other
(defpointer keyword keywordp)
other
(defpointer known-package-alist system-utilities)
other
(defpointer lambda-applicationp system-utilities)
other
(defpointer lambda-body system-utilities)
other
(defpointer lambda-formals system-utilities)
other
(defpointer ld-history-entry-error-flg ld-history)
other
(defpointer ld-history-entry-input ld-history)
other
(defpointer ld-history-entry-stobjs-out ld-history)
other
(defpointer ld-history-entry-stobjs-out/value ld-history)
other
(defpointer ld-history-entry-user-data ld-history)
other
(defpointer ld-history-entry-value ld-history)
other
(defpointer ld-user-stobjs-modified-warning
  user-stobjs-modified-warnings)
other
(defpointer legal-constantp system-utilities)
other
(defpointer legal-variablep system-utilities)
other
(defpointer let-mbe equality-variants-details)
other
(defpointer lex-fix l<)
other
(defpointer lexp l<)
other
(defpointer lisp-programmer-introduction
  introduction-to-programming-in-acl2-for-those-who-know-lisp)
other
(defpointer logicp system-utilities)
other
(defpointer loop$-do do-loop$)
other
(defpointer loop$-for for-loop$)
other
(defpointer make-lambda system-utilities)
other
(defpointer make-lambda-application system-utilities)
other
(defpointer make-lambda-term system-utilities)
other
(defpointer make-list-ac make-list)
other
(defpointer match-free free-variables)
other
(defpointer maybe-convert-to-mv system-utilities)
other
(defpointer measure-theorem termination-theorem)
other
(defpointer member-eq member)
other
(defpointer member-equal member)
other
(defpointer memoization memoize)
other
(defpointer meta-extract-contextual-fact meta-extract)
other
(defpointer meta-extract-formula meta-extract)
other
(defpointer meta-extract-global-fact meta-extract)
other
(defpointer meta-extract-global-fact+ meta-extract)
other
(defpointer meta-extract-rw+-term meta-extract)
other
(defpointer mfc metafunction-context)
other
(defpointer mfc-ancestors extended-metafunctions)
other
(defpointer mfc-ap extended-metafunctions)
other
(defpointer mfc-clause extended-metafunctions)
other
(defpointer mfc-rdepth extended-metafunctions)
other
(defpointer mfc-relieve-hyp extended-metafunctions)
other
(defpointer mfc-rw extended-metafunctions)
other
(defpointer mfc-rw+ extended-metafunctions)
other
(defpointer mfc-ts extended-metafunctions)
other
(defpointer mfc-type-alist extended-metafunctions)
other
(defpointer mfc-unify-subst extended-metafunctions)
other
(defpointer mfc-world extended-metafunctions)
other
(defpointer mode xargs t)
other
(defpointer multiple-value mv-let)
other
(defpointer nfix-list l<)
other
(defpointer no-duplicatesp-eq no-duplicatesp)
other
(defpointer no-duplicatesp-equal no-duplicatesp)
other
(defpointer no-op hints t)
other
(defpointer no-thanks hints t)
other
(defpointer non-executable xargs t)
other
(defpointer nonlinearp hints t)
other
(defpointer normalization normalize)
other
(defpointer note1 note-1-1)
other
(defpointer note2 note-1-2)
other
(defpointer note3 note-1-3)
other
(defpointer note4 note-1-4)
other
(defpointer note5 note-1-5)
other
(defpointer note6 note-1-6)
other
(defpointer note7 note-1-7)
other
(defpointer note8 note-1-8)
other
(defpointer note8-update note-1-8-update)
other
(defpointer note9 note-1-9)
other
(defpointer nvariablep system-utilities)
other
(defpointer observation-cw observation)
other
(defpointer old-and-new-event-data saving-event-data)
other
(defpointer open-input-channel io)
other
(defpointer open-input-channel-p io)
other
(defpointer open-output-channel io)
other
(defpointer open-output-channel-p io)
other
(defpointer optimize declare)
other
(defpointer other-releases releases)
other
(defpointer package packages)
other
(defpointer partition-rest-and-keyword-args
  system-utilities)
other
(defpointer pe-table extend-pe-table)
other
(defpointer peek-char$ io)
other
(defpointer persistent-whs wormhole-status)
other
(defpointer plist-worldp system-utilities)
other
(defpointer position-eq position)
other
(defpointer position-equal position)
other
(defpointer pound-bang-reader sharp-bang-reader)
other
(defpointer pound-dot-reader sharp-dot-reader)
other
(defpointer pound-u-reader sharp-u-reader)
other
(defpointer prettyify-clause system-utilities)
other
(defpointer print-object$-preserving-case io)
other
(defpointer print-summary-user finalize-event-user)
other
(defpointer programp system-utilities)
other
(defpointer proof-supporters-alist dead-events)
other
(defpointer put-assoc-eq put-assoc)
other
(defpointer put-assoc-eql put-assoc)
other
(defpointer put-assoc-equal put-assoc)
other
(defpointer quotep system-utilities)
other
(defpointer rassoc-eq rassoc)
other
(defpointer rassoc-equal rassoc)
other
(defpointer raw-mode set-raw-mode)
other
(defpointer read-byte$ io)
other
(defpointer read-char$ io)
other
(defpointer read-object io)
other
(defpointer read-object-suppress io)
other
(defpointer read-object-with-case io)
other
(defpointer recursivep system-utilities)
other
(defpointer redefine ld-redefinition-action)
other
(defpointer redefining ld-redefinition-action)
other
(defpointer redundant redundant-events)
other
(defpointer regression books-certification)
other
(defpointer remove-assoc-eq remove-assoc)
other
(defpointer remove-assoc-equal remove-assoc)
other
(defpointer remove-duplicates-eq remove-duplicates)
other
(defpointer remove-duplicates-equal remove-duplicates)
other
(defpointer remove-eq remove)
other
(defpointer remove-equal remove)
other
(defpointer remove-guard-holders guard-holders)
other
(defpointer remove1-assoc-eq remove1-assoc)
other
(defpointer remove1-assoc-equal remove1-assoc)
other
(defpointer remove1-eq remove1)
other
(defpointer remove1-equal remove1)
other
(defpointer reorder hints t)
other
(defpointer reset-print-control print-control)
other
(defpointer restrict hints t)
other
(defpointer rewrite-cache set-rw-cache-state)
other
(defpointer ruler-extenders rulers)
other
(defpointer ruler rulers)
other
(defpointer runes-diff saving-event-data)
other
(defpointer rw-cache set-rw-cache-state)
other
(defpointer saving-and-restoring save-exec)
other
(defpointer set-accumulated-persistence
  accumulated-persistence)
other
(defpointer set-difference-eq set-difference$)
other
(defpointer set-difference-equal set-difference$)
other
(defpointer set-fast-cert fast-cert)
other
(defpointer set-ld-always-skip-top-level-locals
  ld-always-skip-top-level-locals)
other
(defpointer set-ld-error-action ld-error-action)
other
(defpointer set-ld-error-triples ld-error-triples)
other
(defpointer set-ld-evisc-tuple ld-evisc-tuple)
other
(defpointer set-ld-keyword-aliases ld-keyword-aliases)
other
(defpointer set-ld-keyword-aliases! ld-keyword-aliases)
other
(defpointer set-ld-missing-input-ok ld-missing-input-ok)
other
(defpointer set-ld-post-eval-print ld-post-eval-print)
other
(defpointer set-ld-pre-eval-filter ld-pre-eval-filter)
other
(defpointer set-ld-pre-eval-print ld-pre-eval-print)
other
(defpointer set-ld-prompt ld-prompt)
other
(defpointer set-ld-query-control-alist
  ld-query-control-alist)
other
(defpointer set-ld-redefinition-action
  ld-redefinition-action)
other
(defpointer set-ld-skip-proofs ld-skip-proofsp)
other
(defpointer set-ld-skip-proofsp ld-skip-proofsp)
other
(defpointer set-ld-user-stobjs-modified-warning
  user-stobjs-modified-warnings)
other
(defpointer set-ld-verbose ld-verbose)
other
(defpointer set-let*-abstraction set-let*-abstractionp)
other
(defpointer set-non-linear set-non-linearp)
other
(defpointer set-print-circle print-control)
other
(defpointer set-print-escape print-control)
other
(defpointer set-print-length print-control)
other
(defpointer set-print-level print-control)
other
(defpointer set-print-lines print-control)
other
(defpointer set-print-readably print-control)
other
(defpointer set-print-right-margin print-control)
other
(defpointer set-proofs-co proofs-co)
other
(defpointer set-ruler-extenders rulers)
other
(defpointer set-serialize-character
  with-serialize-character)
other
(defpointer set-slow-alist-action slow-alist-warning)
other
(defpointer set-standard-co standard-co)
other
(defpointer set-standard-oi standard-oi)
other
(defpointer set-temp-touchable-fns remove-untouchable)
other
(defpointer set-temp-touchable-vars remove-untouchable)
other
(defpointer set-trace-co trace-co)
other
(defpointer show-accumulated-persistence
  accumulated-persistence)
other
(defpointer single-threaded-objects stobj)
other
(defpointer split-types xargs t)
other
(defpointer stable-under-simplificationp computed-hints)
other
(defpointer step-limit with-prover-step-limit)
other
(defpointer stobj-let nested-stobjs)
other
(defpointer stobjp system-utilities)
other
(defpointer stobjs xargs t)
other
(defpointer stobjs-in system-utilities)
other
(defpointer stobjs-out system-utilities)
other
(defpointer subcor-var system-utilities)
other
(defpointer sublis-fn system-utilities)
other
(defpointer sublis-fn-lst-simple system-utilities)
other
(defpointer sublis-fn-simple system-utilities)
other
(defpointer sublis-var system-utilities)
other
(defpointer subsequencep system-utilities)
other
(defpointer subsetp-eq subsetp)
other
(defpointer subsetp-equal subsetp)
other
(defpointer subst-expr system-utilities)
other
(defpointer subst-var system-utilities)
other
(defpointer suitably-tamep-listp tame)
other
(defpointer sum$ loop$)
other
(defpointer sum$+ loop$)
other
(defpointer symbol-class system-utilities)
other
(defpointer symbol-doublet-listp system-utilities)
other
(defpointer table-alist table)
other
(defpointer tag-tree ttree)
other
(defpointer tamep tame)
other
(defpointer tamep-functionp tame)
other
(defpointer tamep-lambdap tame)
other
(defpointer thereis$ loop$)
other
(defpointer thereis$+ loop$)
other
(defpointer time-limit with-prover-time-limit)
other
(defpointer too-many-ifs efficiency)
other
(defpointer top-level-loop guarantees-of-the-top-level-loop)
other
(defpointer trans-eval-default-warning
  user-stobjs-modified-warnings)
other
(defpointer trans-eval-no-warning
  user-stobjs-modified-warnings)
other
(defpointer translate system-utilities)
other
(defpointer translate-hints system-utilities)
other
(defpointer translate1 system-utilities)
other
(defpointer translate11 system-utilities)
other
(defpointer translate-cmp system-utilities)
other
(defpointer translate1-cmp system-utilities)
other
(defpointer ttag defttag)
other
(defpointer trust-tag defttag)
other
(defpointer typespec-check meta-extract)
other
(defpointer undoing undo)
other
(defpointer union-eq union$)
other
(defpointer union-equal union$)
other
(defpointer unknown-constraints partial-encapsulate)
other
(defpointer until$ loop$)
other
(defpointer until$+ loop$)
other
(defpointer untouchable-marker defmacro-untouchable)
other
(defpointer untranslate-preprocess
  user-defined-functions-table)
other
(defpointer use hints t)
other
(defpointer value system-utilities)
other
(defpointer value-cmp context-message-pair)
other
(defpointer variablep system-utilities)
other
(defpointer verify-guards-eagerness
  set-verify-guards-eagerness)
other
(defpointer waterfall hints-and-the-waterfall)
other
(defpointer weak-ld-history-entry-p ld-history)
other
(defpointer when$ loop$)
other
(defpointer when$+ loop$)
other
(defpointer with-output! with-output)
other
(defpointer with-prover-step-limit! with-prover-step-limit)
other
(defpointer wormhole-coherence wormhole-status)
other
(defpointer write-byte$ io)
other
(defpointer *df-pi* df)
other
(defpointer binary-df* df)
other
(defpointer binary-df+ df)
other
(defpointer binary-df-log df)
other
(defpointer binary-df/ df)
other
(defpointer df* df)
other
(defpointer df+ df)
other
(defpointer df- df)
other
(defpointer df-abs df)
other
(defpointer df-abs-fn df)
other
(defpointer df-acos df)
other
(defpointer df-acos-fn df)
other
(defpointer df-acosh df)
other
(defpointer df-acosh-fn df)
other
(defpointer df-asin df)
other
(defpointer df-asin-fn df)
other
(defpointer df-asinh df)
other
(defpointer df-asinh-fn df)
other
(defpointer df-atan df)
other
(defpointer df-atan-fn df)
other
(defpointer df-atanh df)
other
(defpointer df-atanh-fn df)
other
(defpointer df-cos df)
other
(defpointer df-cos-fn df)
other
(defpointer df-cosh df)
other
(defpointer df-cosh-fn df)
other
(defpointer df-exp df)
other
(defpointer df-exp-fn df)
other
(defpointer df-expt df)
other
(defpointer df-expt-fn df)
other
(defpointer df-log df)
other
(defpointer df-minus-1 df)
other
(defpointer df-pi df)
other
(defpointer df-rationalize df)
other
(defpointer df-round df)
other
(defpointer df-sin df)
other
(defpointer df-sin-fn df)
other
(defpointer df-sinh df)
other
(defpointer df-sinh-fn df)
other
(defpointer df-sqrt df)
other
(defpointer df-sqrt-fn df)
other
(defpointer df-string df)
other
(defpointer df-tan df)
other
(defpointer df-tan-fn df)
other
(defpointer df-tanh df)
other
(defpointer df-tanh-fn df)
other
(defpointer df/ df)
other
(defpointer df/=-fn df)
other
(defpointer df0 df)
other
(defpointer df1 df)
other
(defpointer df< df)
other
(defpointer df<-fn df)
other
(defpointer df<= df)
other
(defpointer df= df)
other
(defpointer df=-fn df)
other
(defpointer df> df)
other
(defpointer df>= df)
other
(defpointer dfp df)
other
(defpointer double-float df)
other
(defpointer floating-point df)
other
(defpointer from-df df)
other
(defpointer rize df)
other
(defpointer |The Tours| tours)
other
(defpointer to-df df)
other
(defpointer to-dfp df)
other
(defpointer unary-df- df)
other
(defpointer unary-df-log df)
other
(defpointer unary-df/ df)