Major Section: EVENTS
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.
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 ...]
The following constraint is associated with the function F:
(IMPLIES (CONSP X) (CONSP (F X)))
Summary Form: ( ENCAPSULATE ((F ...) ...) ...) Rules: NIL Warnings: Non-rec Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.00) T ACL2 !>(defun g (x) (declare (xargs :guard (or (consp x) (null x)))) (cons 17 (car x)))
[... output omitted ...] Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) 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 ...] Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) :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> (F (3 4)) 3> (G (3 4)) <3 (G (17 . 3)) <2 (F (17 . 3)) <1 (ACL2_*1*_ACL2::F (17 . 3)) (17 . 3) ACL2 !>
Below we explain defattach
in some detail, but the log above gives the
main idea.
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)))) :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" :in-theory (enable foo)))) (h j :hints (("Goal" :in-theory (enable bar)))) :hints (("Goal" :use my-thm))) ; as above, except attach g to f and attach j to h, with ; the following 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 aboveGeneral Forms: (defattach f g) ; single attach or, if g is nil, unattach (defattach (f1 g1 :hints hints1) (f2 g2 :hints hints2) ... (fk gk :hints hintsk) :hints hints) ; where all :hints are optional, and if any gi is nil, then ; all gi are nil and all :hints are omitted
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,
described in detail below; but here we give a brief introduction 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
.'' The primary exceptions, where we
do not use attachments during evaluation, are for macroexpansion, evaluation
of defconst
and defpkg
terms, evaluation during table
events, and especially evaluation of ground terms (terms without free
variables) by the theorem prover. Regarding the last of these, consider the
following example.
(defstub f (x) t) (defun g (x) (+ 3 x)) (defattach f g)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
, which of course would be unsound since there are no axioms about f
that would justify such a simplification.
For the case that g
is nil
in the first General Form above, we simply
have an abbreviation for the form (defattach (f nil))
. This form results
in removal of the existing attachment of f
, if any. After this removal,
calls of f
will once again cause errors saying that ``ACL2 cannot ev the
call of undefined function ...''.
The rest of this documentation describes the second General Form above, which
is the most general. All hints are optional; their role is described below.
However, i
must be at least 1. The fi
must be distinct constrained
function symbols, that is, function symbols all introduced in signatures
of encapsulate
events (or macros such as defstub
that
generate encapsulate
events). If any gi
is nil
then all gi
must be nil
, in which case no hintsi
is allowed. Assume otherwise.
Then each gi
is a :
logic
-mode function symbol that has had its
guards verified, with the same signature as fi
. This event
generates proof obligations, as described below. If all proofs succeed, then
the effect of this event is first to remove any existing attachments of all
the function symbols fi
, and then to attach each gi
to fi
, in the
sense described above for the first General Form. We may refer to the set of
fi
(still assuming each gi
is non-nil
as the ``attachment nest''
of those fi
.
It is legal to redefine attachments, but only after unattaching any
previously-defined attachment (by ``attaching'' nil
, as described
above). Whenever a function symbol's attachment is removed, so are all
function symbols that received attachments from the same defattach
event.
Proofs must in general be performed before making attachments. For this
discussion we assume that each gi
is non-nil
. ACL2 first proves, for
each i
(in order), that the guard of fi
implies the guard of gi
.
If this sequence of proofs succeeds, then the remaining formula to prove is
formed by first taking the conjunction of the constraints on the symbols
fi
, and then replacing each fi
by gi
. This latter proof
obligation is thus similar to that done on behalf of functional
instantiation; see constraint for a discussion of constraints. As with
functional instantiation, ACL2 stores the fact that such proofs have been
done so that they are avoided in future events (see lemma-instance).
How do we determine the status of a function symbol, fn
, with respect to
attachment? The form (attachment-alist fn (w state)))
evaluates to t
if it is legal to attach a function to (the value of) fn
, but there is
not currently any such attachment. It evaluates to nil
if it is not
legal to attach to fn
. Otherwise, this form evaluates to a non-empty
list of pairs (fi gi)
such that fi
ranges over the elements of the
attachment nest of f
, and for each i
, gi
is the attachment of
fi
. To see all attachments: (all-attachments (w state))
.