other
(in-package "GL")
other
(include-book "std/util/bstar" :dir :system)
other
(include-book "centaur/misc/beta-reduce-full" :dir :system)
scan-lemmas-for-numefunction
(defun scan-lemmas-for-nume (lemmas nume) (declare (xargs :mode :program)) (b* (((when (endp lemmas)) nil) (rule (car lemmas)) ((when (eql (access rewrite-rule rule :nume) nume)) (cons rule (scan-lemmas-for-nume (cdr lemmas) nume)))) (scan-lemmas-for-nume (cdr lemmas) nume)))
scan-props-for-nume-lemmafunction
(defun scan-props-for-nume-lemma (props nume) (declare (xargs :mode :program)) (and (consp props) (append (and (eq (cadar props) 'lemmas) (scan-lemmas-for-nume (cddar props) nume)) (scan-props-for-nume-lemma (cdr props) nume))))
collect-lemmas-for-runefunction
(defun collect-lemmas-for-rune (rune world) (declare (xargs :mode :program)) (b* ((nume (runep rune world)) ((unless nume) nil) (segment (world-to-next-event (cdr (decode-logical-name (cadr rune) world))))) (scan-props-for-nume-lemma (actual-props segment nil nil) nume)))
collect-lemmas-for-runesfunction
(defun collect-lemmas-for-runes (runes world) (declare (xargs :mode :program)) (if (atom runes) nil (append (b* ((rune (car runes))) (collect-lemmas-for-rune (if (symbolp rune) `(:rewrite ,GL::RUNE) rune) world)) (collect-lemmas-for-runes (cdr runes) world))))
gl-rewrite-table-entries-for-lemmasfunction
(defun gl-rewrite-table-entries-for-lemmas (rune lemmas) (if (atom lemmas) nil (cons (b* ((fnsym (car (access rewrite-rule (car lemmas) :lhs)))) `(table gl-rewrite-rules ',GL::FNSYM (b* ((rules (cdr (assoc ',GL::FNSYM (table-alist 'gl-rewrite-rules world))))) (if (member-equal ',GL::RUNE rules) rules (cons ',GL::RUNE rules))))) (gl-rewrite-table-entries-for-lemmas rune (cdr lemmas)))))
alist-add-gl-rulesfunction
(defun alist-add-gl-rules (rules alist) (declare (xargs :mode :program)) (if (atom rules) alist (b* ((fnsym (car (access rewrite-rule (car rules) :lhs))) (rune (access rewrite-rule (car rules) :rune)) (new-alist (put-assoc-eq fnsym (add-to-set-equal rune (cdr (assoc-eq fnsym alist))) alist))) (alist-add-gl-rules (cdr rules) new-alist))))
alist-add-gl-rewritefunction
(defun alist-add-gl-rewrite (rune alist world) (declare (xargs :mode :program)) (b* ((rune (if (symbolp rune) `(:rewrite ,GL::RUNE) rune)) (rules (collect-lemmas-for-rune rune world))) (alist-add-gl-rules rules alist)))
alist-add-gl-rewritesfunction
(defun alist-add-gl-rewrites (runes alist world) (declare (xargs :mode :program)) (b* ((rules (collect-lemmas-for-runes runes world))) (alist-add-gl-rules rules alist)))
add-gl-rewrite-fnfunction
(defun add-gl-rewrite-fn (rune world) (declare (xargs :mode :program)) (b* ((rune (if (symbolp rune) `(:rewrite ,GL::RUNE) rune)) (rules (collect-lemmas-for-rune rune world)) ((unless rules) (er hard 'add-gl-rewrite-fn "No rules found for rune ~x0." rune))) `(table gl-rewrite-rules nil (alist-add-gl-rules ',GL::RULES (table-alist 'gl-rewrite-rules world)) :clear)))
add-gl-rewritemacro
(defmacro add-gl-rewrite (rune) `(make-event (add-gl-rewrite-fn ',GL::RUNE (w state))))
alist-remove-gl-rulesfunction
(defun alist-remove-gl-rules (rules alist) (declare (xargs :mode :program)) (if (atom rules) alist (b* ((fnsym (car (access rewrite-rule (car rules) :lhs))) (rune (access rewrite-rule (car rules) :rune)) (new-alist (put-assoc-eq fnsym (remove-equal rune (cdr (assoc-eq fnsym alist))) alist))) (alist-remove-gl-rules (cdr rules) new-alist))))
alist-remove-gl-rewritefunction
(defun alist-remove-gl-rewrite (rune alist world) (declare (xargs :mode :program)) (b* ((rune (if (symbolp rune) `(:rewrite ,GL::RUNE) rune)) (rules (collect-lemmas-for-rune rune world))) (alist-remove-gl-rules rules alist)))
alist-remove-gl-rewritesfunction
(defun alist-remove-gl-rewrites (runes alist world) (declare (xargs :mode :program)) (b* ((rules (collect-lemmas-for-runes runes world))) (alist-remove-gl-rules rules alist)))
remove-gl-rewrite-fnfunction
(defun remove-gl-rewrite-fn (rune world) (declare (xargs :mode :program)) (b* ((rune (if (symbolp rune) `(:rewrite ,GL::RUNE) rune)) (rules (collect-lemmas-for-rune rune world)) ((unless rules) (er hard 'remove-gl-rewrite-fn "No rules found for rune ~x0." rune))) `(table gl-rewrite-rules nil (alist-remove-gl-rules ',GL::RULES (table-alist 'gl-rewrite-rules world)) :clear)))
remove-gl-rewritemacro
(defmacro remove-gl-rewrite (rune) `(make-event (remove-gl-rewrite-fn ',GL::RUNE (w state))))
other
(defsection def-gl-rewrite :parents (reference term-level-reasoning) :short "Define a rewrite rule for GL to use on term-level objects" :long "<p>GL can use ACL2-style rewrite rules to simplify term-level symbolic objects. However, typically one wants a different theory for ACL2 theorem proving than one wants to use inside GL. @('GL::DEF-GL-REWRITE') defines a rewrite rule that is only used inside GL:</p> @({ (gl::def-gl-rewrite my-rewrite-rule (implies (and (syntaxp (and (integerp n) (< 0 (integer-length n)))) (< 0 m)) (equal (logand n m) (logcons (b-and (logcar n) (logcar m)) (logand (logcdr n) (logcdr m))))) :hints ...) }) <p>This defines a disabled ACL2 rewrite rule called my-rewrite-rule, and adds my-rewrite-rule to the table of rules GL is allowed to use. (GL will still use it even though it is disabled, as long as it is in that table.)</p> <p>Def-gl-rewrite supports syntaxp hypotheses, but the term representation used is different from ACL2's. Instead of being bound to TERMPs, the variables are bound to symbolic objects. See @(see gl::symbolic-objects) for reference.</p>" (defmacro def-gl-rewrite (name &rest args) `(progn (defthmd ,GL::NAME . ,GL::ARGS) (add-gl-rewrite ,GL::NAME))))
gl-rewrite-table-entries-for-lemma-removalsfunction
(defun gl-rewrite-table-entries-for-lemma-removals (rune lemmas) (if (atom lemmas) nil (cons (b* ((fnsym (car (access rewrite-rule (car lemmas) :lhs)))) `(table gl-rewrite-rules ',GL::FNSYM (b* ((rules (cdr (assoc ',GL::FNSYM (table-alist 'gl-rewrite-rules world))))) (if (member-equal ',GL::RUNE rules) (remove ',GL::RUNE rules) rules)))) (gl-rewrite-table-entries-for-lemma-removals rune (cdr lemmas)))))
gl-set-uninterpreted-fnfunction
(defun gl-set-uninterpreted-fn (fn val world) (b* ((formals (getprop fn 'formals :none 'current-acl2-world world)) (fn (if (eq formals :none) (cdr (assoc fn (table-alist 'macro-aliases-table world))) fn)) (formals (if (eq formals :none) (getprop fn 'formals :none 'current-acl2-world world) formals)) ((when (eq formals :none)) (er hard? 'gl-set-uninterpreted-fn "~x0 is neither a function nor a macro-alias for a function~%" fn))) `(table gl-uninterpreted-functions ',GL::FN ,GL::VAL)))
other
(defsection gl-set-uninterpreted :parents (reference term-level-reasoning) :short "Prevent GL from interpreting a function's definition or concretely executing it." :long "<p>Usage:</p> @({ ;; disallow definition expansion and concrete execution (gl::gl-set-uninterpreted fnname) (gl::gl-set-uninterpreted fnname t) ;; same as above ;; disallow definition expansion but allow concrete execution (gl::gl-set-uninterpreted fnname :concrete-only) ;; disallow concrete execution but allow definition expansion (gl::gl-set-uninterpreted fnname :no-concrete) ;; remove restrictions (gl::gl-set-uninterpreted fnname nil) (gl::gl-unset-uninterpreted fnname) ;; same }) <p>prevents GL from opening the definition of fnname and/or concretely executing it. GL will still apply rewrite rules to a call of @('fnname'). If the call is not rewritten away, symbolic execution of a @('fnname') call will simply produce an object (of the :g-apply type) representing a call of @('fnname') on the given arguments.</p> <p>@('gl::gl-unset-uninterpreted') undoes the effect of @('gl::gl-set-uninterpreted').</p> <p>Note that @('gl::gl-set-uninterpreted') has virtually no effect when applied to a GL primitive: a function that has its ``symbolic counterpart'' built into the GL clause processor you're using. (It actually does do a little — it can prevent the function from being applied to concrete values before rewrite rules are applied. But that could change in the future.) But what is a GL primitive? That depends on the current GL clause processor, and can only be determined reliably by looking at the definition of the following function symbol:</p> @({ (cdr (assoc-eq 'gl::run-gified (table-alist 'gl::latest-greatest-gl-clause-proc (w state)))) }) <p>For example, this function symbol is 'gl::glcp-run-gified immediately after including the community-book @('"centaur/gl/gl"'). Now use @(':')@(tsee pe) on this function symbol. The body of that definition should be of the form @('(case fn ...)'), which matches @('fn') against all the GL primitives for the current GL clause processor.</p> " (defmacro gl-set-uninterpreted (fn &optional (val 't)) `(make-event (gl-set-uninterpreted-fn ',GL::FN ,GL::VAL (w state)))))
gl-unset-uninterpretedmacro
(defmacro gl-unset-uninterpreted (fn) `(make-event (gl-set-uninterpreted-fn ',GL::FN nil (w state))))
gl-branch-merge-rulesfunction
(defun gl-branch-merge-rules (wrld) (declare (xargs :guard (plist-worldp wrld))) (cdr (hons-assoc-equal 'gl-branch-merge-rules (table-alist 'gl-branch-merge-rules wrld))))
add-gl-branch-merge-fnfunction
(defun add-gl-branch-merge-fn (rune) (declare (xargs :mode :program)) (b* ((rune (if (symbolp rune) `(:rewrite ,GL::RUNE) rune))) `(table gl-branch-merge-rules 'gl-branch-merge-rules (add-to-set-equal ',GL::RUNE (gl-branch-merge-rules world)))))
add-gl-branch-mergemacro
(defmacro add-gl-branch-merge (rune) (add-gl-branch-merge-fn rune))
other
(defsection def-gl-branch-merge :parents (reference term-level-reasoning) :short "Define a rule for GL to use in merging IF branches" :long "<p>Usage:</p> @({ (gl::def-gl-branch-merge my-branch-merge-rule (implies (and (syntaxp (integerp m)) (integerp m)) (equal (if cond (logcons b n) m) (logcons (if cond b (logcar m)) (if cond n (logcdr m))))) :hints ...) }) <p>This form creates an ACL2 theorem with :rule-classes nil and installs it in a table that GL references when attempting to merge branches of an IF term.</p> <p>Branch merge rules work similarly to normal rewrite rules, except that:</p> <ul> <li>the LHS must be of the form: @('(if <var> <then-term> <else-term>)')</li> <li>each rule is indexed by the function symbol of the then-term, so then-term must be a function call.</li> </ul>" (defun def-gl-branch-merge-fn (name body hints otf-flg) `(progn (defthm ,GL::NAME ,GL::BODY :hints ,GL::HINTS :otf-flg ,GL::OTF-FLG :rule-classes nil) (add-gl-branch-merge ,GL::NAME))) (defmacro def-gl-branch-merge (name body &key hints otf-flg) (def-gl-branch-merge-fn name body hints otf-flg)))
translate-pairfunction
(defun translate-pair (pair ctx state) (declare (xargs :stobjs state :mode :program)) (b* (((list a b) pair) ((er aa) (translate a t t t ctx (w state) state)) ((er bb) (translate b t t t ctx (w state) state))) (value (list aa bb))))
translate-pair-listfunction
(defun translate-pair-list (pairs ctx state) (declare (xargs :stobjs state :mode :program)) (b* (((when (atom pairs)) (value nil)) ((er first) (translate-pair (car pairs) ctx state)) ((er rest) (translate-pair-list (cdr pairs) ctx state))) (value (cons first rest))))
def-glcp-ctrex-rewrite-fnfunction
(defun def-glcp-ctrex-rewrite-fn (from test tos state) (declare (xargs :mode :program :stobjs state)) (b* (((er fromtrans) (translate-pair from 'def-gplcp-ctrex-rewrite state)) ((er tostrans) (translate-pair-list tos 'def-gplcp-ctrex-rewrite state)) ((er testtrans) (translate test t t t 'def-gplcp-ctrex-rewrite (w state) state)) (entry (list* fromtrans testtrans tostrans)) (fnsym (caar fromtrans))) (value `(table glcp-ctrex-rewrite ',GL::FNSYM (cons ',GL::ENTRY (cdr (assoc ',GL::FNSYM (table-alist 'glcp-ctrex-rewrite world))))))))
other
(defsection def-glcp-ctrex-rewrite :parents (reference term-level-reasoning) :short "Define a heuristic for GL to use when generating counterexamples" :long "<p>Usage:</p> @({ (gl::def-glcp-ctrex-rewrite ;; from: (lhs-lvalue lhs-rvalue) ;; to: (rhs-lvalue rhs-rvalue) :test syntaxp-term) }) <p>Example:</p> @({ (gl::def-glcp-ctrex-rewrite ((logbitp n x) t) (x (logior (ash 1 n) x)) :test (quotep n)) }) <p>If GL has generated Boolean variables corresponding to term-level objects, then an assignment to the Boolean variables does not directly induce an assignment of ACL2 objects to the ACL2 variables. Instead, we have terms that are assigned true or false by the Boolean assignment, and to generate a counterexample, we must find an assignment for the variables in those terms that cause the terms to take the required truth values. Ctrex-rewrite rules tell GL how to move from a valuation of a term to valuations of its components.</p> <p>The example rule above says that if we want @('(logbitp n x)') to be @('t'), and @('n') is (syntactically) a quoted constant, then assign @('x') a new value by effectively setting its @('n')th bit to T (that is, bitwise ORing X with the appropriate mask).</p> <p>Note that this rule does not always yield the desired result -- for example, in the case where N is a negative integer. Because these are just heuristics for generating counterexamples, there is no correctness requirement and no checking of these rules. Bad counterexample rules can't make anything unsound, but they can cause generated counterexamples to be nonsense. Be careful!</p>" (defmacro def-glcp-ctrex-rewrite (from to &key (test 't)) `(make-event (def-glcp-ctrex-rewrite-fn ',GL::FROM ',GL::TEST ',(LIST GL::TO) state))))
def-glcp-ctrex-split-rewritemacro
(defmacro def-glcp-ctrex-split-rewrite (from tos &key (test 't)) `(make-event (def-glcp-ctrex-rewrite-fn ',GL::FROM ',GL::TEST ',GL::TOS state)))