Major Section: MISCELLANEOUS
Sometimes an event will announce that it is ``redundant''. When this happens, no change to the logical world has occurred. This happens when the logical name being defined is already defined and has exactly the same definition, from the logical point of view. This feature permits two independent books, each of which defines some name, to be included sequentially provided they use exactly the same definition.
When are two logical-name definitions considered exactly the same? It depends upon the kind of name being defined.
A deflabel
event is never redundant. This means that if you have a
deflabel
in a book and that book has been included (without error),
then references to that label denote the point in history at which
the book introduced the label. See the note about shifting logical
names, below.
A defun
or mutual-recursion
(or defuns
) event is redundant
if for each function to be introduced, there has already been introduced a
function with the same name, the same formals, and syntactically identical
guard
, type declarations, stobj
s
declarations and body
(before macroexpansion), and an appropriate mode
.
Exception: if either definition is declared :non-executable
(see xargs),
then the two events must be identical. We discuss the situation with
``appropriate mode
s'' below.
A verify-guards
event is redundant if the function has already had
its guards verified.
A defaxiom
or defthm
event is redundant if there is already an axiom
or theorem of the given name and both the formula (after
macroexpansion) and the rule-classes are syntactically identical.
Note that a defaxiom
can make a subsequent defthm
redundant, and a
defthm
can make a subsequent defaxiom
redundant as well.
A defconst
is redundant if the name has been defined to have the
same value.
A defstobj
is never redundant. Blah blah...
A defmacro
is redundant if there is already a macro defined with the
same name and syntactically identical arguments, guard, and body.
A defpkg
is redundant if a package of the same name with exactly the
same imports has been defined.
A deftheory
is never redundant. The ``natural'' notion of
equivalent deftheory
s is that the names and values of the two theory
expressions are the same. But since most theory expressions are
sensitive to the context in which they occur, it seems unlikely to
us that two deftheory
s coming from two sequentially included books
will ever have the same values. So we prohibit redundant theory
definitions. If you try to define the same theory name twice, you
will get a ``name in use'' error.
An in-theory
event is never redundant because it doesn't define any
name.
A push-untouchable
event is redundant if every name supplied is
already a member of the untouchable symbols.
Table
and defdoc
events are never redundant because they don't
define any name.
An encapsulate
event is redundant if and only if a syntactically
identical encapsulate
has already been executed under the same
default-defun-mode
.
An include-book
is redundant if the book has already been included.
Note About Appropriate Modes:
Suppose a function is being redefined and that the formals, guards, types,
stobjs, and bodies are identical. When are the modes (:
program
or :
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 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. This is inappropriate. We do not permit the
downgrading of a function from :logic
mode to :program
mode, since
that might produce a logical world in which there were theorems about a
:program
mode function, violating one of ACL2's basic assumptions.
Note About Shifting Logical Names:
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 world in which fn
is not already defined, i.e., in a
world in which the book's definition of fn
is not redundant. In
session B, the book is included in a 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 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.
This may adversely affect the user of your book. For example,
suppose your book creates a theory via 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:
(set-difference-theories (universal-theory :here) (universal-theory fn))where
fn
is the very first event in the book and happens to be a
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.
The moral of this is simple: when building books that other people
will use, it is best to describe your theories in terms of logical
names that will not shift around when the books are included. The
best such names are those created by deflabel
.