/usr/share/acl2-6.3/books/cutil/maybe-defthm.lisp is in acl2-books-source 6.3-5.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | ; CUTIL - Centaur Basic Utilities
; Copyright (C) 2008-2011 Centaur Technology
;
; Contact:
; Centaur Technology Formal Verification Group
; 7600-C N. Capital of Texas Highway, Suite 300, Austin, TX 78731, USA.
; http://www.centtech.com/
;
; This program is free software; you can redistribute it and/or modify it under
; the terms of the GNU General Public License as published by the Free Software
; Foundation; either version 2 of the License, or (at your option) any later
; version. This program is distributed in the hope that it will be useful but
; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
; more details. You should have received a copy of the GNU General Public
; License along with this program; if not, write to the Free Software
; Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
;
; Original author: Jared Davis <jared@centtech.com>
(in-package "CUTIL")
(include-book "tools/bstar" :dir :system)
; This book is an awful hack to work around a problem with ACL2.
;
; ACL2 will not allow you to submit a theorem like this:
;
; (defthm crock
; (equal (consp x) (consp x)))
;
; That's reasonable, I guess, since such a rule would loop.
;
; Unfortunately, ACL2 is "smart" enough to simplify your rule, before even
; trying to prove that it holds, using certain kinds of type reasoning. For
; instance, if you try to submit:
;
; (defthm not-nil
; (equal (not nil) t))
;
; ACL2 will use type reasoning to reduce (NOT NIL) to T, and then it will
; reject your rule on the grounds that you are rewriting T to itself.
;
; That's fine until you try to write a macro like DEFLIST/DEFALIST. Here, the
; user gives us some predicate and also may tell us, e.g., that their predicate
; is true for NIL. Now, for many reasons---to check whether they've told us
; the truth, and to fail quickly and in an obvious way if they haven't, and to
; make sure we're operating in a reliable theory---we try to submit a perfectly
; reasonable theorem:
;
; (defthm predicate-of-nil
; (equal (predicate nil) t))
;
; If PREDICATE is something interesting like INTEGER-LISTP, this theorem will
; go through fine and all is well. But when the predicate is something simple
; like NOT or INTEGERP, ACL2 helpfully simplifies (PREDICATE NIL) to T and then
; bombs out.
;
; Here is a horrible way to work around this.
(defmacro maybe-defthm-as-rewrite
;; Submit a rewrite rule only if it's not going to run afoul of this check.
(name ; Name of the theorem you want to write, e.g., predicate-of-nil
concl ; Conclusion of your theorem, e.g., (equal (predicate 'nil) 't)
&key hints)
"Concl must be a HYP-FREE and already TRANSLATED term"
`(make-event
(b* ((name ',name)
(concl ',concl)
(hints ',hints)
((unless (pseudo-termp concl))
(er hard? 'maybe-defthm-as-rewrite
"Expected concl to be a translated term, but got ~x0"
concl)
(value '(value-triple :error)))
(thm `(defthm ,name ,concl :hints ,hints))
(ens (acl2::ens state))
(wrld (acl2::w state))
;; Call ACL2's function that checks whether the rule is okay or not.
((mv msg ?eqv ?lhs ?rhs ?ttree)
(acl2::interpret-term-as-rewrite-rule name nil concl ens wrld))
((when msg)
;; Not okay! Don't submit the theorem.
(value '(value-triple :invisible))))
;; Okay -- submit it!
(value thm))))
(defun is-theorem-p (name world)
(declare (xargs :mode :program))
;; Checks whether NAME is the name of a defined theorem.
(acl2::fgetprop name 'acl2::theorem nil world))
(defmacro enable-if-theorem (name)
;; Enables NAME if it is a valid theorem, or does nothing otherwise.
`(make-event
(let ((name ',name))
(if (is-theorem-p name (w state))
(value `(in-theory (enable ,name)))
(value `(value-triple :invisible))))))
(defmacro disable-if-theorem (name)
;; Disables NAME if it is a valid theorem, or does nothing otherwise.
`(make-event
(let ((name ',name))
(if (is-theorem-p name (w state))
(value `(in-theory (disable ,name)))
(value `(value-triple :invisible))))))
(local
(progn
;; Some basic tests
(include-book "misc/assert" :dir :system)
(maybe-defthm-as-rewrite foo (equal (car (cons x y)) x))
(maybe-defthm-as-rewrite bar (equal (not 'nil) 't))
(maybe-defthm-as-rewrite baz (equal (stringp 'nil) 'nil))
(assert! (is-theorem-p 'foo (w state)))
(assert! (not (is-theorem-p 'bar (w state))))
(assert! (not (is-theorem-p 'baz (w state))))
(assert! (let ((acl2::ens (acl2::ens state))) (active-runep '(:rewrite foo))))
(assert! (let ((acl2::ens (acl2::ens state))) (not (active-runep '(:rewrite bar)))))
(enable-if-theorem foo)
(assert! (let ((acl2::ens (acl2::ens state)))
(active-runep '(:rewrite foo))))
(disable-if-theorem foo)
(assert! (let ((acl2::ens (acl2::ens state)))
(not (active-runep '(:rewrite foo)))))
(enable-if-theorem foo)
(assert! (let ((acl2::ens (acl2::ens state)))
(active-runep '(:rewrite foo))))
))
|