:u
or :
ubt
Major Section: HISTORY
The keyword command :oops
will undo the most recent :
ubt
(or :u
,
which we here consider just another :
ubt
). A second :oops
will undo
the next most recent :
ubt
, a third will undo the :
ubt
before that
one, and a fourth :oops
will return the logical world to its
configuration before the first :oops
.
Consider the logical world (see world) that represents the
current extension of the logic and ACL2's rules for dealing with it.
The :
ubt
and :u
commands ``roll back'' to some previous world
(see ubt). Sometimes these commands are used to inadvertently
undo useful work and user's wish they could ``undo the last undo.''
That is the function provided by :oops
.
:Oops
is best described in terms of an implementation. Imagine a
ring of four worlds and a marker (*
) indicating the current ACL2
world:
* w0 / \ w3 w1 \ / w2This is called the ``kill ring'' and it is maintained as follows. When you execute an event the current world is extended and the kill ring is not otherwise affected. When you execute
:
ubt
or :u
, the
current world marker is moved one step counterclockwise and that
world in the ring is replaced by the result, say w0'
, of the :
ubt
or
:u
.
w0 / \ *w0' w1 \ / w2If you were to execute events at this point,
w0'
would be extended
and no other changes would occur in the kill ring.
When you execute :oops
, the marker is moved one step clockwise.
Thus the kill ring becomes * w0 / \ w0' w1 \ / w2
and the current
ACL2 world is w0
once again. That is, :oops
``undoes'' the :
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 world. Note however that a fourth :oops
restores us to the configuration above.
In general, the kill ring contains the current world and the three
most recent worlds in which a :
ubt
or :u
were done.
While :
ubt
may appear to discard the information in the events
undone, we can see that the world in which the :
ubt
occurred is
still available. No information has been lost about that world.
But :
ubt
does discard information! :
Ubt
discards the information
necessary to recover from the third most recent ubt
! An :oops
, on
the other hand, discards no information, it just selects the next
available world on the kill ring and doing enough :oops
es will
return you to your starting point.
We can put this another way. You can freely type :oops
and inspect
the world that you thus obtain with :
pe
, :
pc
, and other history
commands. You can repeat this as often as you wish without risking
the permanent loss of any information. But you must be more careful
typing :
ubt
or :u
. While :oops
makes :
ubt
seem ``safe'' because the
most recent :
ubt
can always be undone, information is lost when you
execute :
ubt
.
Major Section: HISTORY
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 commandsSee command-descriptor.
Pbt
takes one argument, a command descriptor, and prints the
commands from :
max
(aka :x
) through the one described.
See command-descriptor for a description of what a command
descriptor is. See pc for a description of the format used to
display commands. Pbt
will print the commands that ubt
will
undo.
Major Section: HISTORY
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 fnSee command-descriptor.
Pc
takes one argument, a command descriptor, and prints the command
identified by that descriptor. See command-descriptor. For
example
ACL2 !>:pc foo LVd 52 (DEFUN FOO (X) X)
Pc
always prints a space first, followed by three (possibly blank)
characters (``LVd'' above) explained below. Then pc
prints the
command number, a number uniquely identifying the command's position
in the sequence of commands since the beginning of the user's
session. Finally, the command itself is printed.
While pc
always prints a space first, some history commands, for
example :
pcs
and :
pe
, use the first column of output to delimit a
region of commands or to point to a particular event within a
command.
For example, :pcs 52 54
will print something like
/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)Here, the two slash characters in the first column are intended to suggest a bracket delimiting commands 52 through 54. The last command printed by
pcs
is always the most recent command, i.e., the
command at :here
, and is separated from the rest of the display by
an elipsis if some commands are omitted.
Similarly, the :
pe
command will print a particular event within a
command block and will indicate that event by printing a ``>
'' in
the first column. The symbol is intended to be an arrow pointing at
the event in question.
For example, :
pe
true-listp-app
might print:
1 (INCLUDE-BOOK "list-book") \ > (DEFTHM TRUE-LISTP-APP (EQUAL (TRUE-LISTP (APP A B)) (TRUE-LISTP B)))using the arrow to indicate the event itself. The slash printed to connect the command,
include-book
, with the event, defthm
, is
intended to suggest a tree branch indicating that the event is
inferior to (and part of) the command.The mysterious three characters sometimes preceding a command have the following interpretations. The first two have to do with the function symbols introduced by the command and are blank if no symbols were introduced.
At any time we can classify our function symbols into three disjoint
sets, which we will here name with characters. The ``P
''
functions are those in :
program
mode. The ``L
'' functions are
those in :
logic
mode whose guards have not been verified. The
``V
'' functions are those in :
logic
mode whose guards have
been verified. Note that verify-termination
and verify-guards
cause function symbols to be reclassified. If a 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).
Thus, the display
PLd 52 (DEFUN FOO (X) X)tells us that command 52 introduced a
:
program
function but that
some command after 52 changed its mode to :
logic
and that the
guards of foo
have not been verified. That is, foo
's
termination has been verified even though it was not verified as
part of the command that introduced foo
. Had a subsequent
command verified the guards of foo
, the display would contain a
V
where the L
is.The display
P d 52 (DEFUN FOO (X) X)indicates that
foo
was introduced in :
program
mode and still
is in that mode.
The third character indicates the enabled/disabled status of the
runes introduced by the command. If the status character is blank
then all the runes (if any) introduced are enabled. If the status
character is ``D
'' then some runes were introduced and they are
all disabled. If the status character is ``d
'' then at least
one, but not all, of the runes introduced is disabled. Thus, in the
display
L d 52 (DEFUN FOO (X) X)we see that some rune introduced by command 52 is disabled. As noted in the documentation for rune, a
defun
command
introduces many runes, e.g., the axiomatic definition rule,
(:definition fn)
, the executable counterpart rule,
(:executable-counterpart fn)
, and type-prescriptions,
(:type-prescription fn)
. The display above does not say which of
the runes based on foo
is disabled, but it does tell us one of
them is.
Major Section: HISTORY
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 blockSee command-descriptor.
Pcb
takes one argument, a command descriptor, and prints the command
block of the command described. See command-descriptor for
details of command descriptors. See pc for description of the
format in which commands are displayed. The command block of a
command consists of the command itself and all of the 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 defun
or defthm
rather than a macro that expanded to some event
forms), then pcb
just prints the command. Pcb
sketches command and
all of the events it created, rather than printing them fully. If
you wish to see just the command, in its entirety, use pc
. If you
wish to see one of the events within the block, in its entirety, use
pe
. If you wish to see the command sketched and all of the events
it created, in their entirety, use pcb!
.
Major Section: HISTORY
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 blockSee command-descriptor.
Pcb!
takes one argument, a command descriptor, and prints the
command block of the command described. Unlike pcb
, pcb!
prints the
event forms in full; see pcb for details.
Major Section: HISTORY
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
Pcs
takes two arguments, both of which are command descriptors, and
prints the commands between them with pc
. The order of the two
descriptors is irrelevant. See command-descriptor for a
description of command descriptors. See pc for a description
of the format in which commands are displayed.
Major Section: HISTORY
Example: :pe fn ; sketches the command that introduced fn and ; prints in full the event within it that created fn.See logical-name.
Pe
takes one argument, a logical name, and prints in full the most
recent event corresponding to the name. Pe
also sketches the
command responsible for that event if the command is different from
the event itself. See pc for a description of the format used
to display a command. To remind you that the event is inferior to
the command, i.e., you can only undo the entire command, not just
the event, the event is indented slightly from the command and a
slash (meant to suggest a tree branch) connects them.
Use pe!
if you want all events corresponding to a given name;
see pe!.
Major Section: HISTORY
Examples: :pe! name ; prints each event that corresponds to name.
Pe!
takes one argument, a logical name other than :here
, and prints
in full all the events for that name. Pe!
also sketches the command
responsible for that event in each case that the command is
different from the event itself. See pc for a description of
the format used to display a command. To remind you that the event
is inferior to the command, i.e., you can only undo the entire
command, not just the event, the event is indented slightly from the
command and a slash (meant to suggest a tree branch) connects them.
Use pe
if you want only the latest event corresponding to a given
name, or if you want to use the logical name :here
; see pe.
Major Section: HISTORY
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
takes one argument, an event name or a rune, and prints the
formula associated with name.
Major Section: HISTORY
Examples: :pl foo ; prints the rewrite rules that rewrite some call of foo
Pl
takes one argument, a function symbol, and displays the lemmas
that rewrite some term whose top function symbol is the given one.
Note that names of macros are not relevant here; for example, for
the rules about +
you should give the command :pl
binary-+
.
In fact the kinds of rules printed by :pl
are rewrite rules,
definition rules, and meta rules.
Major Section: HISTORY
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
Also see pr!, which is similar but works at the command level instead of at the event level.
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:
Rune: (:LINEAR ABC) Status: Enabled Hyps: ((CONSP X)) Concl: (< (ACL2-COUNT (CAR X)) (ACL2-COUNT X)) Max-term: (ACL2-COUNT (CAR X)) Fixer: NILThe
hyps
and concl
fields for this rule are fairly
self-explanatory, but it is useful to see linear to learn about
maximal terms (which, as one might guess, are stored under
``Max-term''). In order to learn about the ``Fixer'' one has to
know to see linear-alias, which is quite unreasonable. The
state of this documentation will surely improve.Currently, this function does not print congruence rules or equivalence rules.
The expert user might also wish to use find-rules-of-rune
.
See find-rules-of-rune.
Major Section: HISTORY
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
Also see pr, which is similar but works at the event level instead of at the command level.
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 pr for further details.
Major Section: HISTORY
Example Forms: ACL2 !>:puff :max ACL2 !>:puff :x ACL2 !>:puff 15 ACL2 !>:puff "book"whereGeneral Form: :puff cd
cd
is a command descriptor (see command-descriptor) for
a ``puffable'' command (see below). Puff
replaces the command at cd
by the immediate subevents of the command, executed as commands.
Puff
then prints, using pcs
, the puff
ed region.
A command is ``puffable'' if it is an encapsulate
command, an
include-book
command, or any command other than those consisting of
a single primitive event. For example, since defun
is a primitive
event, a defun
command is not puffable. But a macro form that
expands into several defun
events is puffable. The only primitive
event commands that are puffable are encapsulate
and include-book
commands. A puffable command contains (interesting) subevents,
namely, the events in the body of the encapsulate
, in the file of
the book included, or in the command block.
The puff command ``lifts'' the immediate subevents of the indicated
command so that they become commands themselves. The command puff*
recursively puffs the newly introduced commands. See puff*,
which also gives an example illustrating both puff
and puff*
. Puff
undoes the command at cd
and replaces it by its immediate subevents.
Thus, in general the length of the history grows when a puff command
is executed. If puff
causes an error (see below), the logical world
remains unchanged from its initial configuration.
The intended use of puff
is to allow the user access to the events
``hidden'' inside compound commands. For example, while trying to
prove some theorem, p
, about a constrained function, fn
, one might
find that the encapsulate
, cd
, that introduced fn
failed to include
an important constraint, q
. Without puff
, the only way to proceed
is to undo back through cd
, create a suitable encapsulate
that
proves and exports q
as well as the old constraints, re-execute the
new encapsulate
, re-execute the events since cd
, and then try p
again. Unfortunately, it may be hard to prove q
and additional
events may have to be inserted into the encapsulate
to prove it. It
may also be hard to formulate the ``right'' q
, i.e., one that is
provable in the encapsulate
and provides the appropriate facts for
use in the proof of p
.
Using puff
, the user can erase the encapsulate
at cd
, replacing it
by the 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 state -- where fn
is constrained rather than
defined and q
is exported by an encapsulate
at cd
-- 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.
Similar applications of puff
allow the user of a book to expose the
innards of the book as though they had all be typed as commands.
The user might then ``partially undo'' the book, keeping only some
of the events in it.
Puff
operates as follows. First, it determines the list of
immediate subevents of the command indicated by cd
. It causes an
error if there is only one subevent and that subevent is identical
to the command -- i.e., if the command at cd
is a primitive. Next,
puff
undoes back through the indicated command. This not only
erases the command at cd
but all the commands executed after it.
Finally, puff
re-executes the subevents of (the now erased) cd
followed by all the commands that were executed afterwards.
Observe that the commands executed after cd
will generally have
higher command numbers than they did before the puff. For example,
suppose 100 commands have been executed and that :puff 80
is then
executed. Suppose command 80 contains 5 immediate subevents (i.e.,
is an encapsulation of five events). Then, after puffing, command
80 is the first event of the puffed command, command 81 is the
second, and so on; 104 commands appear to have been executed.
When puffing an encapsulate
or include-book
, the local
commands are
executed. Note that this will replace constrained functions by
their witnesses.
Finally, it is impossible to puff
in the presence of include-book
commands involving certified files that have been altered since they
were included. 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 command that
included "arith"
. The attempt to obtain the subevents in
"arith"
will discover that the check sum of "arith"
has changed
and an error will be caused. No change is made in the logical
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 world
unchanged even if the command puffed is not one involving the
modified book. This happens because in order to reconstruct the
world after the puffed command, puff
must obtain the events in the
book and if the book's source file has changed there is no assurance
that the reconstructed world is the one the user intends.
Warning: We do not detect changes to uncertified books that have
been included and are then puffed or re-included! The act of
including an uncertified book leaves no trace of the check sum of
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.
Major Section: HISTORY
Example Forms: ACL2 !>:puff* :max ACL2 !>:puff* :x ACL2 !>:puff* 15 ACL2 !>:puff* "book"whereGeneral Form: :puff* cd
cd
is a command descriptor (see command-descriptor) for
a ``puffable'' command. See puff for the definition of
``puffable'' and for a description of the basic act of ``puffing'' a
command. Puff*
is just the recursive application of puff. Puff*
prints the region puffed, using pcs
.
To puff a command is to replace it by its immediate subevents, each
of which is executed as a command. To puff*
a command is to replace
the command by each of its immediate subevents and then to puff*
each of the puffable commands among the newly introduced ones.
For example, suppose "ab"
is a book containing the following
(in-package "ACL2") (include-book "a") (include-book "b")Suppose that book
"a"
only contained defun
s for the functions a1
and a2
and that "b"
only contained defun
s for b1
and b2
.
Now consider an ACL2 state in which only two commands 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 :
pbt
1 would be:
1 (INCLUDE-BOOK "ab") 2 (INCLUDE-BOOK "c")Call this state the ``starting state'' in this example, because we will refer to it several times.
Suppose :puff 1
is executed in the starting state. Then the first
command is replaced by its immediate subevents and :pbt 1
would
show:
1 (INCLUDE-BOOK "a") 2 (INCLUDE-BOOK "b") 3 (INCLUDE-BOOK "c")Contrast this with the execution of
:puff* 1
in the starting
state. Puff*
would first puff (include-book "ab")
to get the
state shown above. But then it would recursively puff*
the puffable
commands introduced by the first puff. This continues recursively
as long as any puff introduced a puffable command. The end result
of :puff* 1
in the starting state is
1 (DEFUN A1 ...) 2 (DEFUN A2 ...) 3 (DEFUN B1 ...) 4 (DEFUN B2 ...) 5 (INCLUDE-BOOK "c")Observe that when
puff*
is done, the originally indicated command,
(include-book "ab")
, has been replaced by the corresponding
sequence of primitive events. Observe also that puffable commands
elsewhere in the history, for example, command 2 in the starting
state, are not affected (except that their command numbers grow as a
result of the splicing in of earlier commands).
Major Section: HISTORY
Example: :u
The keyword command :u
is the same as :
ubt
:
max
, but with related
queries suppressed appropriately. :
Oops
will undo the last :u
.
See ubt and see ubt!.
Major Section: HISTORY
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 commandsSee command-descriptor.
ubt
takes one argument, a command descriptor, and undoes the
commands from :
max
(aka :x
) through the one described.
See command-descriptor. Pbt
will print the commands that ubt
will undo. :
Oops
will undo the undo. See oops.
It is important to remember that a command may create several
events. That is, the command that introduces fn1
may also introduce
fn2
. Undoing the command that created either of these will undo
them both. The events created by a command constitute the command's
``block'' and we can only undo entire blocks. Use pcb
to print the
command block of a command if you wish to see what will be lost by
undoing the command.
Ubt
will not undo into ``prehistory''. :Ubt 1
will undo all of your
commands. But :ubt -5
will cause an error, warning you that :ubt
cannot undo system initialization.
Major Section: HISTORY
Example: :ubt! :x-4
The keyword command :ubt!
is the same as :
ubt
, but with related
queries suppressed appropriately, and with a guarantee that it is
``error-free.'' More precisely, the error triple returned by :ubt!
will always have a first component of nil
. :
Oops
will undo the last
:ubt!
. See ubt and see u.