Define a non-executable
This event is provided for those who want to experiment with defattach using
See community book
Example Forms: (defproxy subr1 (* *) => *) (defproxy add-hash (* * hashtable) => (mv * hashtable)) General Form: (defproxy name args-sig => output-sig)
where
The macro
In order to take advantage of a defproxy form, one provides a
subsequent
The following log shows a simple use of defproxy.
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 !>
One can replace this attachment with one that uses
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 !>
We close with some remarks on the checking of guards in the case
that defattach has been called with keyword argument
First suppose that
(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)
If we try to evaluate the form
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 !>
Little changes if we modify the example above by strengthening the guard of
(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)
The result of evaluating
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 !>
Now consider a slight variation of the example just above, in which
(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)
Since
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 !>
If you replace