Info file: acl2-doc-lemacs.info,    -*-Text-*-
produced by `texinfo-format-buffer'
from file `acl2-doc-lemacs.texinfo'
using `texinfmt.el' version 2.32 of 19 November 1993.



This is documentation for ACL2 Version 1.8 Copyright (C) 1989-95
Computational Logic, Inc. (CLI).  All rights reserved.





File: acl2-doc-lemacs.info, Node: COMPRESS2, Next: DEFAULT, Prev: COMPRESS1, Up: ARRAYS

COMPRESS2    remove irrelevant pairs from a 2-dimensional array


     Example Form:
     (compress2 'delta1 a)

     General Form:
     (compress2 name alist)

where name is a symbol and alist is a 2-dimensional array named name.
*Note ARRAYS:: for details.  Logically speaking, this function removes
irrelevant pairs from alist, possibly shortening it.  The function
returns a new array, alist', of the same name and dimension as alist,
that, under 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.

Practically speaking, this function plays an important role in the
efficient implementation of 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 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 aset2 on name.
*Note ARRAYS::.



File: acl2-doc-lemacs.info, Node: DEFAULT, Next: DIMENSIONS, Prev: COMPRESS2, Up: ARRAYS

DEFAULT    return the :default from the header of a 1- or 2-dimensional array


     Example Form:
     (default 'delta1 a)

     General Form:
     (default name alist)

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
header of alist.  When aref1 or 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.  *Note ARRAYS::.



File: acl2-doc-lemacs.info, Node: DIMENSIONS, Next: HEADER, Prev: DEFAULT, Up: ARRAYS

DIMENSIONS    return the :dimensions from the header of a 1- or 2-dimensional array


     Example Form:
     (dimensions 'delta1 a)

     General Form:
     (dimensions name alist)

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 guards on aref1.
Dimensions operates in virtually constant time if alist is the semantic
value of name.  *Note ARRAYS::.



File: acl2-doc-lemacs.info, Node: HEADER, Next: MAXIMUM-LENGTH, Prev: DIMENSIONS, Up: ARRAYS

HEADER    return the header of a 1- or 2-dimensional array


     Example Form:
     (header 'delta1 a)

     General Form:
     (header name alist)

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.
*Note ARRAYS::.



File: acl2-doc-lemacs.info, Node: MAXIMUM-LENGTH, Next: SLOW-ARRAY-WARNING, Prev: HEADER, Up: ARRAYS

MAXIMUM-LENGTH    return the :maximum-length from the header of an array


     Example Form:
     (maximum-length 'delta1 a)

     General Form:
     (maximum-length name alist)

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 header of alist.  Whenever an aset1 or
aset2 would cause the length of the alist to exceed its maximum
length, a compress1 or 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.
*Note ARRAYS::.



File: acl2-doc-lemacs.info, Node: SLOW-ARRAY-WARNING, Prev: MAXIMUM-LENGTH, Up: ARRAYS

SLOW-ARRAY-WARNING    a warning issued when arrays are used inefficiently

If you use ACL2 arrays you may sometimes see a *slow array* warning.  We
here explain what that warning means and some likely "mistakes" it may
signify.

The discussion in the documentation for 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.  Aset1 and compress1
modify the raw lisp array appropriately to maintain the invariant.

If 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, aref1 prints a *slow array* warning message to the comment
window.  Aset1 behaves similarly because the array it returns will cause
the *slow array* warning every time it is used.

From the purely logical perspective there is nothing "wrong" about such
use of arrays and it may be spurious to print a warning message.  But
because arrays are generally used to achieve efficiency, the *slow
array* 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.

Here are some "mistakes" that might cause this behavior.  In the
following we suppose the message was printed by aset1 about an array
named name.  Suppose the alist supplied aset1 is alist.

(1) Compress1 was never called on name and alist.  That is, perhaps you
created an alist that is an array1p and then proceeded to access it with
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.

(2) Name is misspelled.  Perhaps the array was compressed under the name
'delta-1 but accessed under 'delta1?

(3) An 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 aset1.
Then write

     (let ((alist (aset1 name alist i val))) ...)

and make sure that the subsequent function body is entirely within the
scope of the 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

      (foo (let ((alist (aset1 name alist i val))) ...)  ; arg 1
           (bar alist))                                  ; arg 2

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 let out:

      (let ((alist (aset1 name alist alist i val)))
        (foo ...                                         ; arg 1
             (bar alist)))                               ; arg 2

Of course, this may not mean the same thing.

(4) A function which takes alist as an argument and modifies it with
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 aset1 (or a subfunction
uses aset1, etc.), then the function probably "ought" to return the
result produced by 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.



File: acl2-doc-lemacs.info, Node: BIBLIOGRAPHY, Next: BREAKS, Prev: ARRAYS, Up: MISCELLANEOUS

BIBLIOGRAPHY    reports about ACL2

Below is a list of notes and reports pertaining to ACL2.

R. Boyer, M. Kaufmann, and J Moore, "A short note on some advantages of
Acl2."  CLI Internal Note 215, Jan., 1991.  See the files
reports/note-215-acl2-advantages.* under the ACL2 source directory.

"High-level Correctness of ACL2: A Story."  See the file
reports/story.txt under the ACL2 source directory.

M. Kaufmann and J Moore, "Design Goals for ACL2."  CLI Technical Report
101, August, 1994.  See the files reports/acl2-design.* under the ACL2
source directory.



File: acl2-doc-lemacs.info, Node: BREAKS, Next: CHECK-SUM, Prev: BIBLIOGRAPHY, Up: MISCELLANEOUS

BREAKS    Common Lisp breaks


     Example:
     Broken at PROVE.  Type :H for Help.
     >>:Q

     ACL2 !>


If a break occurs, e.g. 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 prompts 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.

Quitting from the break (as with :q in AKCL) will return to the
innermost ACL2 read-eval-print loop.  Before the loop is continued, any
pending cleanup forms from acl2-unwind-protects are evaluated (unless
acl2::*acl2-panic-exit-flg* is non-nil, in which case no cleanup is
done).

If at any time you type the token #. to either a raw lisp break or to
the ACL2 read-eval-print loop, an abort is executed.  Control is passed
to the outermost ACL2 read-eval-print loop (lp).  Again,
unwind-protection cleanup forms are executed first.



File: acl2-doc-lemacs.info, Node: CHECK-SUM, Next: COMMAND, Prev: BREAKS, Up: MISCELLANEOUS

CHECK-SUM    assigning "often unique" integers to files and objects

A "check sum" 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 characters in the printed representation.

Ideally, you would like the check sum 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 check sum (which is relatively small) and when an object is
presented to you and alleged to be the special one you could compute its
check sum and see if indeed it was.  Alas, there are many more objects
than check sums (after all, each check sum is an object, and then
there's t).  So you try to design a check sum algorithm that maps
similar looking objects far apart, in the hopes that corruptions and
counterfeits -- which appear to be similar to the object -- have
different check sums.  Nevertheless, the best you can do is a
many-to-one map.  If an object with a different check sum is presented,
you can be positive it is not the special object.  But if an object with
the same check sum is presented, you have no grounds for positive
identification.

The basic check sum algorithm in ACL2 is called check-sum-obj, which
computes the check sum 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.

ACL2 uses check sums to increase security in the books mechanism; *Note
CERTIFICATE::.



File: acl2-doc-lemacs.info, Node: COMMAND, Next: COMMAND-DESCRIPTOR, Prev: CHECK-SUM, Up: MISCELLANEOUS

COMMAND    forms you type at the top-level, but...

...the word "command" usually refers to a top-level form whose
evaluation produces a new logical world.

     Typical commands are:
     (defun foo (x) (cons x x))
     (defthm consp-foo (consp (foo x)))
     (defrec pair (hd . tl) nil)

The first two forms are examples of commands that are in fact primitive
events.  *Note EVENTS::.  defrec, on the other hand, is a macro that
expands into a progn of several primitive events.  In general, a world
extending command generates one or more events.

Both events and commands leave landmarks on the world that enable us
to determine how the given 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.
*Note COMMAND-DESCRIPTOR::.



File: acl2-doc-lemacs.info, Node: COMMAND-DESCRIPTOR, Next: CONSTRAINT, Prev: COMMAND, Up: MISCELLANEOUS

COMMAND-DESCRIPTOR    an object describing a particular command typed by the user


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


The recorded history of your interactions with the top-level ACL2
command loop is marked by the commands you typed that changed the
logical world.  Each such command generated one or more events, since
the only way for you to change the logical world is to execute an event
function.  *Note COMMAND:: and *Note EVENTS::.  We divide history into
"command blocks," grouping together each world changing command and its
events.  A "command descriptor" is an object that can be used to
describe a particular command in the history of the ongoing session.

Each command is assigned a unique integer called its "command number"
which indicates the command's position in the chronological ordering of
all of the commands ever executed in this session (including those
executed to initialize the system).  We assign the number 1 to the first
command you type to ACL2.  We assign 2 to the second and so on.  The
non-positive integers are assigned to "prehistoric" commands, i.e., the
commands used to initialize the ACL2 system: 0 is the last command of
the initialization, -1 is the one before that, etc.

The legal command descriptors are described below.  We use n to denote
any integer, sym to denote any logical name (*Note LOGICAL-NAME::), and
cd to denote, recursively, any command descriptor.

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




File: acl2-doc-lemacs.info, Node: CONSTRAINT, Next: COPYRIGHT, Prev: COMMAND-DESCRIPTOR, Up: MISCELLANEOUS

CONSTRAINT    restrictions on certain functions introduced in encapsulate events

Suppose that a given theorem, thm, is to be functionally instantiated
using a given functional substitution, alist, as described in :DOC
lemma-instance.  What is the set of proof obligations generated?  It is
the set of all terms, tm, such that (a) tm mentions some function symbol
in the domain of alist, and (b) either tm arises from the "constraint"
on a function symbol ancestral in thm or some defaxiom or (ii) tm is the
body of a 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.

The remainder of this note explains what we mean by "constraint" in the
words above.

In a certain sense, function symbols are introduced in essentially
two ways.  The most common way is to use defun (or when there is
mutual recursion, mutual-recursion or defuns).  There is also
a mechanism for introducing "witness functions";
*Note DEFCHOOSE::.  The documentation for these 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.

However, when a function symbol is introduced in the scope of an
encapsulate event, its constraints may differ from the definitional
axioms introduced for it.  For example, suppose that a function's
definition is local to the encapsulate; that is, suppose the function is
introduced in the signature of the encapsulate.  Then its constraints
include, at the least, those non-local theorems and definitions in the
encapsulate that mention the function symbol.

Actually, it will follow from the discussion below that if the signature
is empty for an 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 include-book
events.  But the general case, where the signature is not empty, is more
complicated.

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 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 events as being "lifted" out of the encapsulate, resulting in a
possibly smaller encapsulate, which becomes the target of the algorithm
described in the first cut.

At the end of this note we present an example showing why a more naive
approach is unsound.

Finally, before we start our "first cut," we note that constrained
functions always have guards of T.  This makes sense when one considers
that a constrained function's "guard" only appears in the context of a
local defun, which is skipped.  Note also that any information you want
"exported" outside an 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 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 mv functions) in a context where you are
verifying guards, then you should probably provide a :type-prescription
rule for the constrained function, for example, the :type-prescription
rule (true-listp (foo x)).

*First cut at constraint-assigning algorithm.*  Quite simply, the
formulas introduced in the scope of an encapsulate are conjoined, and
each function symbol introduced by the encapsulate is assigned that
conjunction as its constraint.

Clearly this is a rather severe algorithm.  Let us consider two possible
optimizations in an informal manner before presenting our second cut.

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.

     (encapsulate
      ((sig-fn (x) t))

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

We would like to imagine moving the definition of before1 to just in
front of this encapsulate, as follows.

     (defun before1 (x)
       (if (consp x)
           (before1 (cdr x))
         x))

     (encapsulate
      ((sig-fn (x) t))

      (local (defun sig-fn (x) (cons x x)))

      (defthm sig-fn-prop
        (consp (sig-fn x)))
      )

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.

More generally, suppose an event in an encapsulate event does not
mention any function symbol in the signature of the encapsulate, nor any
function symbol that mentions any such function symbol, and so on.  (We
might say that no function symbol from the 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 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, and such
theorems introduce no constraints.

Once this first optimization is performed, we have in mind a set of
"constrained functions."  These are the functions introduced in the
encapsulate that would remain after moving some of them out, as
indicated above.  Consider the collection of all formulas introduced by
the 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.

     (encapsulate
      ((sig-fn (x) t))

      (local (defun sig-fn (x) (cons x x)))

      (defthm sig-fn-prop
        (consp (sig-fn x)))

      (defun after1 (x)
        (sig-fn x))
      )

We can see that there is really no harm in imagining that we move the
definition of after1 out of the encapsulate, to just after the
encapsulate.

We may summarize the observations above as follows, after which we
conclude with a more elaborate example.

*Second cut at constraint-assigning algorithm.*  Given an
encapsulate event, first move, to just in front of it and in the same
order, all definitions and theorems for which none of the functions
declared in the signature is ancestral.  (In fact perform this process
recursively, handling nested encapsulates.)  Now collect up all formulas
introduced in the encapsulate other than the definitional axioms, and
restrict the set of constrained functions to those that are ancestral in
at least one such formula.  Finally, assign all formulas introduced in
the resulting encapsulate as the common constraint on all function
symbols that are introduced in the resulting encapsulate.  (Thus, we
imagine that the definitions of functions that are omitted from this
list of function symbols, together with all non-definitional formulas
omitted from this list of formulas, are moved outside the encapsulate,
to just after it.)

Implementation note.  In the implementation we do not actually move
events, but we create constraints that pretend that we did.

Here is an example illustrating our constraint-assigning algorithm.  It
builds on the preceding examples.

     (encapsulate
      ((sig-fn (x) t))

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

Only the functions sig-fn and during receive extra constraints.  The
functions before1 and before2 are viewed as moving in front of the
encapsulate, as is the theorem before2-prop.  The functions after1 and
after2 are viewed as being moved past the encapsulate.  Notice that the
formula (consp (during x)) is a conjunct of the constraint.  It comes
from the :type-prescription rule deduced during the definition of the
function during.  The implementation reports the following.

     (SIG-FN X) is axiomatized to return one result.

     In addition, we export AFTER2, AFTER1, DURING-PROP, BEFORE2-PROP, BEFORE2,
     DURING, SIG-FN-PROP 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 (DURING X))
          (CONSP (SIG-FN X))
          (IMPLIES (AND (ATOM X) (BEFORE2 X))
                   (EQUAL (CAR (DURING X))
                          (CAR (SIG-FN X)))))


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


     (encapsulate
      ((foo (x) t))
      (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))))))))

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 signatures 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 proveable
because foo can be instantiated in foo-id to a function other than the
identity function.

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.

     (encapsulate
      ((foo (x) t))
      (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))))))))





File: acl2-doc-lemacs.info, Node: COPYRIGHT, Next: COROLLARY, Prev: CONSTRAINT, Up: MISCELLANEOUS

COPYRIGHT    ACL2 copyright, license, sponsorship

"ACL2" is an acronym for "A Computational Logic for
Applicative Common Lisp."  ACL2 is copyrighted by Computational
Logic, Inc.  All rights reserved.  For copyright and license
information, see the file "LICENSE".  Also
*Note ACKNOWLEDGEMENTS::.



File: acl2-doc-lemacs.info, Node: COROLLARY, Next: CURRENT-PACKAGE, Prev: COPYRIGHT, Up: MISCELLANEOUS

COROLLARY    the corollary formula of a rune

This is a low-level system function at the present time.
*Note PR:: and *Note PR!:: instead.  Also *Note RULE-CLASSES::for the use of the symbol :corollary in specifying a rule
class.



File: acl2-doc-lemacs.info, Node: CURRENT-PACKAGE, Next: DEFAULT-DEFUN-MODE, Prev: COROLLARY, Up: MISCELLANEOUS

CURRENT-PACKAGE    the package used for reading and printing

Current-package is an ld special (*Note 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 defpkg by the user.

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.

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.

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 deus ex machina ("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 deus ex machina
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.

A simple rule suffices to make sane file 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.



File: acl2-doc-lemacs.info, Node: DEFAULT-DEFUN-MODE, Next: DEFAULT-PRINT-PROMPT, Prev: CURRENT-PACKAGE, Up: MISCELLANEOUS

DEFAULT-DEFUN-MODE    the default defun-mode of defun'd functions

When a defun is processed and no :mode xarg is supplied, the
function default-defun-mode is used.  To find the default defun-mode
of the current ACL2 world, type (default-defun-mode (w state)).
*Note DEFUN-MODE:: for a discussion of defun-modes.  To change the
default defun-mode of the ACL2 world, type one of the keywords :program
or :logic.

The default ACL2 prompt displays the current default defun-mode by
showing the character p for :program mode, and omitting it for
:logic mode; *Note DEFAULT-PRINT-PROMPT::.  The default defun-mode
may be changed using the keyword commands :program and :logic,
which are equivalent to the commands (program) and (logic).
Each of these names is documented separately:  *Note PROGRAM:: and
*Note LOGIC::.  The default defun-mode is stored in the table
acl2-defaults-table and hence may also be changed by a table command.
*Note TABLE:: and also *Note ACL2-DEFAULTS-TABLE::.  Both mode-changing
commands are events.

While events that change the default defun-mode are permitted within an
encapsulate or the text of a book, their effects are local in scope to
the duration of the encapsulation or inclusion.  For example, if the
default defun-mode is :logic and a book is included that contains the
event (program), then subsequent events within the book are processed
with the default defun-mode :program; but when the include-book event
completes, the default defun-mode will still be :logic.  Commands that
change the default defun-mode are not permitted inside local forms.



File: acl2-doc-lemacs.info, Node: DEFAULT-PRINT-PROMPT, Next: DEFUN-MODE, Prev: DEFAULT-DEFUN-MODE, Up: MISCELLANEOUS

DEFAULT-PRINT-PROMPT    the default prompt printed by ld


     Example prompt:
     ACL2 p!s>

The prompt printed by ACL2 displays the current package, followed by a
space, followed by zero or more of the three characters as specified
below, followed by the character > printed one or more times, reflecting
the number of recursive calls of ld.  The three characters in the middle
are as follows:

     p     ; when (default-defun-mode (w state)) is :program
     !     ; when guard checking is on
     s     ; when (ld-skip-proofsp state) is t

*Note DEFAULT-DEFUN-MODE::, *Note SET-GUARD-CHECKING::, and
*Note LD-SKIP-PROOFSP::.

Also *Note LD-PROMPT:: to see how to install your own prompt.

Here are some examples with ld-skip-proofsp nil.

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

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

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





File: acl2-doc-lemacs.info, Node: DEFUN-MODE, Next: DEFUN-MODE-CAVEAT, Prev: DEFAULT-PRINT-PROMPT, Up: MISCELLANEOUS

DEFUN-MODE    determines whether a function definition is a logical act

Two "defun-modes" are supported, :program and :logic.  Roughly speaking,
:program mode allows you to prototype a function for execution without
any proof burdens, while :logic mode allows you to add a new
definitional axiom to the logic.  The system comes up in :logic mode.
Execution of functions whose defun-mode is :program may render ACL2
unsound!  *Note DEFUN-MODE-CAVEAT::.

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 insure that the logic is sound after the
addition of this axiom, certain restrictions have to be met, namely that
the recursion terminates.  This can be quite challenging.

Because ACL2 is a 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 -- 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 data base.  The termination arguments for such
functions are an unnecessary burden provided no axioms about the
functions are ever used in deductions.

Thus, ACL2 introduces the idea of the "defun-mode" of a function.
The :mode keyword of defun's declare xarg allows you to
specify the defun-mode of a given definition.  If no :mode
keyword is supplied, the default defun-mode is used;
*Note DEFAULT-DEFUN-MODE::.

There are two defun-modes, each of which is written as a keyword:

:program -- logically undefined but executable outside deductive
contexts.

:logic -- axiomatically defined as per the ACL2 definitional principle.

It is possible to change the defun-mode of a function from :program to
:logic.  We discuss this below.

We think of functions having :program mode as "dangerous" functions,
while functions having :logic mode are "safe."  The only requirement
enforced on :program mode functions is the syntactic one: each
definition must be well-formed ACL2.  Naively speaking, if a :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
:program mode execution is faulty because it ignores the damage that
might be caused by "mis-guarded" functions.  *Note DEFUN-MODE-CAVEAT::.

We therefore implicitly describe an imagined implementation of
defun-modes that is safe and, we think, effective.  But please
*Note DEFUN-MODE-CAVEAT::.

The default defun-mode is :logic.  This means that when you defun a
function the system will try to prove termination.  If you wish to
introduce a function of a different defun-mode use the :mode xargs
keyword.  Below we show fact introduced as a function in :program mode.

     (defun fact (n)
       (declare (xargs :mode :program))
       (if (or (not (integerp n)) (= n 0))
           1
         (* n (fact (1- n)))))

No axiom is added to the logic as a result of this definition.  By
introducing fact in :program mode we avoid the burden of a termination
proof, while still having the option of executing the function.  For
example, you can type

     ACL2 !>(fact 3)

and get the answer 6.  If you type (fact -1) you will get a hard lisp
error due to "infinite recursion."

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 (*Note DEFUN-MODE-CAVEAT::),
the introduction of this function in :program mode does not imperil the
soundness of the system -- despite the fact that the termination
argument for fact was omitted -- 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.

It is possible to convert a function from :program mode to :logic mode
at the cost of proving that it is admissible.  This can be done by
invoking

     (verify-termination fact)

which is equivalent to submitting the defun of fact, again, but in
:logic mode.

     (defun fact (n)
       (declare (xargs :mode :logic))
       (if (or (not (integerp n)) (= n 0))
           1
         (* n (fact (1- n)))))

This particular event will fail because the termination argument
requires that n be nonnegative.  A repaired defun, for example with =
replaced by <=, will succeed, and an axiom about fact will henceforth be
available.

Technically, verify-termination submits a redefinition of the :program
mode function.  This is permitted, even when ld-redefinition-action is
nil, because the new definition is identical to the old (except for its
:mode and, possibly, other non-logical properties).

*Note GUARD:: for a discussion of how to restrict the execution of
functions.  Guards may be "verified" for functions in :logic mode; *Note
VERIFY-GUARDS::.



File: acl2-doc-lemacs.info, Node: DEFUN-MODE-CAVEAT, Next: DEFUNS, Prev: DEFUN-MODE, Up: MISCELLANEOUS

DEFUN-MODE-CAVEAT    functions with defun-mode of :program considered unsound

Technically speaking, in the current implementation, the execution of
functions having defun-mode :program may damage the ACL2 system in a way
that renders it unsound.  *Note DEFUN-MODE:: for a discussion of
defun-modes.  That discussion describes an imagined implementation that
is slightly different from this one.  This note explains that the
current implementation is open to unsoundness.

For discussion of a different soundness issue that is also related to
function execution, *Note GENERALIZED-BOOLEANS::.

The execution of a function having defun-mode :program may violate
Common Lisp guards on the subroutines used.  (This may be true even for
calls of a function on arguments that satisfy its guard, because ACL2
has not verified that its guard is sufficient to protect its
subroutines.)  When a 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.

For example, suppose you make the following defun:


     (defun crash (i)
       (declare (xargs :mode :program :guard (integerp i)))
       (car i))


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 car expression is in violation of its guard.
Because this function is admitted in :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.


     ACL2 !>(crash 7)

     Error: Caught fatal error [memory may be damaged]
     ...

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.

THUS, HAVING A FUNCTION WITH DEFUN-MODE :PROGRAM IN YOUR SYSTEM ABSOLVES
US, THE ACL2 IMPLEMENTORS, FROM RESPONSIBILITY FOR THE SOUNDNESS OF OUR
SYSTEM.

Furthermore

ACL2 DOES NOT YET PROVIDE ANY MEANS OF REGAINING ASSURANCES OF SOUNDNESS
AFTER THE INTRODUCTION OF A FUNCTION IN :PROGRAM MODE, EVEN IF IT IS
ULTIMATELY CONVERTED TO :LOGIC MODE (since its execution could have
damaged the system in a way that makes it possible to verify its
termination and guards unsoundly).

Finally,

THE VAST MAJORITY OF ACL2 SYSTEM CODE IS IN :PROGRAM MODE AND SO ALL
BETS ARE OFF FROM BEFORE YOU START!

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 :logic mode.  We think
it very unlikely that a mis-guarded function in :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 :program mode.  In that imagined implementation,
code using functions having :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 :program mode, use them as convenient and perhaps
ultimately introduce some of them in :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
:PROGRAM MODE!



File: acl2-doc-lemacs.info, Node: DEFUNS, Next: DISABLE-FORCING, Prev: DEFUN-MODE-CAVEAT, Up: MISCELLANEOUS

DEFUNS    an alternative to mutual-recursion


     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)

is equivalent to

     (MUTUAL-RECURSION
       (DEFUN . defuns-tuple1)
       ...
       (DEFUN . defuns-tuplen))

In fact, defuns is the more primitive of the two and
mutual-recursion is just a macro that expands to a call of defun
after stripping off the defun at the car of each argument to
mutual-recursion.  We provide and use mutual-recursion rather than
defuns because by leaving the defuns in place, mutual-recursion
forms can be processed by the Emacs tags program.
*Note MUTUAL-RECURSION::.



File: acl2-doc-lemacs.info, Node: DISABLE-FORCING, Next: DISABLEDP, Prev: DEFUNS, Up: MISCELLANEOUS

DISABLE-FORCING    to disallow forced case splits


     General Form:
     ACL2 !>:disable-forcing   ; disallow forced case splits

*Note FORCE:: for a discussion of forced case splits.

Disable-forcing is a macro that disables the executable counterpart of
the function symbol force; *Note FORCE::.  When you want to disable
forcing in hints, use a form such as:

     :in-theory (disable (:executable-counterpart force))





File: acl2-doc-lemacs.info, Node: DISABLEDP, Next: E0-ORD-<, Prev: DISABLE-FORCING, Up: MISCELLANEOUS

DISABLEDP    determine whether a given name or rune is disabled


     Examples:

     :disabledp foo   ; returns a list of all disabled runes whose base
                      ; symbol is foo (*Note 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


Also *Note PR::, which gives much more information about the rules
associated with a given event.

Disabledp takes one argument, an event name or a rune.  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; *Note RUNE::).  In
the latter case it returns t if the given rune is disabled, and nil
otherwise.



File: acl2-doc-lemacs.info, Node: E0-ORD-<, Next: E0-ORDINALP, Prev: DISABLEDP, Up: MISCELLANEOUS

E0-ORD-<    the well-founded less-than relation on ordinals up to epsilon-0

If x and y are both e0-ordinalps (*Note E0-ORDINALP::) then (e0-ord-< x
y) is true iff x is strictly less than y.  e0-ord-< is well-founded on
the e0-ordinalps.  When x and y are both nonnegative integers, e0-ord-<
is just the familiar < relation.

e0-ord-< 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 recurses 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.

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 e0-ord-<.  The validity of this method rests
on the well-foundedness of e0-ord-< on the e0-ordinalps.

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 e0-ordinalp.  Furthermore,
consider any recursive call, (f (d x)), in the body of the definition.
Let hyps be the conjunction terms (each of which is either the test of
an 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

       (IMPLIES hyps (E0-ORD-< (m (d x)) (m x))).

When we say e0-ord-< is "well-founded" on the e0-ordinalps we mean that
there is no infinite sequence of e0-ordinalps 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.

*Note E0-ORDINALP:: for a discussion of the ordinals and how to
compare two ordinals.

The definitional principle permits the use of relations other than
e0-ord-< but they must first be proved to be well-founded on some
domain.  *Note WELL-FOUNDED-RELATION::.  Roughly put, alternative
relations are shown well-founded by providing an order-preserving
mapping from their domain into the ordinals.  *Note DEFUN:: for details
on how to specify which well-founded relation is to be used.



